Merge branch 'mv/maint-branch-m-symref' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 9 Nov 2008 00:07:37 +0000 (16:07 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 9 Nov 2008 00:07:37 +0000 (16:07 -0800)
* mv/maint-branch-m-symref:
update-ref --no-deref -d: handle the case when the pointed ref is packed
git branch -m: forbid renaming of a symref
Fix git update-ref --no-deref -d.
rename_ref(): handle the case when the reflog of a ref does not exist
Fix git branch -m for symrefs.

1  2 
builtin-send-pack.c
cache.h
refs.c
diff --combined builtin-send-pack.c
index 301f23043262059dcb28994527334ba1909671f0,ea1ad6e35f59ef361b40e8f5a54bc9fc9940e59a..ed94f9a460336d84ef5c1edcc0c4b5a26163c74d
@@@ -132,13 -132,7 +132,13 @@@ static struct ref *remote_refs, **remot
  static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
  {
        struct ref *ref;
 -      int len = strlen(refname) + 1;
 +      int len;
 +
 +      /* we already know it starts with refs/ to get here */
 +      if (check_ref_format(refname + 5))
 +              return 0;
 +
 +      len = strlen(refname) + 1;
        ref = xcalloc(1, sizeof(*ref) + len);
        hashcpy(ref->new_sha1, sha1);
        memcpy(ref->name, refname, len);
@@@ -232,7 -226,7 +232,7 @@@ static void update_tracking_ref(struct 
                if (args.verbose)
                        fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
                if (ref->deletion) {
-                       delete_ref(rs.dst, NULL);
+                       delete_ref(rs.dst, NULL, 0);
                } else
                        update_ref("update by push", rs.dst,
                                        ref->new_sha1, NULL, 0, 0);
diff --combined cache.h
index 74339edaaa2bc5fbf3e920d66a8bca9cc5b785d3,715348a0663e278d4eecc0c04c0ad9b8148493b2..39f24ad827a419740e2c7515e0e8f294424cd9b0
+++ b/cache.h
@@@ -270,7 -270,6 +270,7 @@@ static inline void remove_name_hash(str
  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
  #define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
 +#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
  #endif
  
  enum object_type {
@@@ -383,7 -382,6 +383,7 @@@ extern int add_to_index(struct index_st
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
 +extern int index_name_is_other(const struct index_state *, const char *, int);
  
  /* do stat comparison even if CE_VALID is true */
  #define CE_MATCH_IGNORE_VALID         01
@@@ -413,8 -411,6 +413,8 @@@ struct lock_file 
        char on_list;
        char filename[PATH_MAX];
  };
 +#define LOCK_DIE_ON_ERROR 1
 +#define LOCK_NODEREF 2
  extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
  extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
  extern int commit_lock_file(struct lock_file *);
@@@ -424,7 -420,7 +424,7 @@@ extern int commit_locked_index(struct l
  extern void set_alternate_index_output(const char *);
  extern int close_lock_file(struct lock_file *);
  extern void rollback_lock_file(struct lock_file *);
- extern int delete_ref(const char *, const unsigned char *sha1);
+ extern int delete_ref(const char *, const unsigned char *sha1, int delopt);
  
  /* Environment bits from configuration mechanism */
  extern int trust_executable_bit;
diff --combined refs.c
index 9e422dcccbb3d499b55df5f39612b12c3c3f52e0,0d239e15b08b9ccf798700ff4b93b4a85f416d7d..156714e54ee6c980a48f01610d78d10301e849b7
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -790,7 -790,7 +790,7 @@@ static struct ref_lock *lock_ref_sha1_b
        struct ref_lock *lock;
        struct stat st;
        int last_errno = 0;
 -      int type;
 +      int type, lflags;
        int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
  
        lock = xcalloc(1, sizeof(struct ref_lock));
  
        lock->lk = xcalloc(1, sizeof(struct lock_file));
  
 -      if (flags & REF_NODEREF)
 +      lflags = LOCK_DIE_ON_ERROR;
 +      if (flags & REF_NODEREF) {
                ref = orig_ref;
 +              lflags |= LOCK_NODEREF;
 +      }
        lock->ref_name = xstrdup(ref);
        lock->orig_ref_name = xstrdup(orig_ref);
        ref_file = git_path("%s", ref);
                error("unable to create directory for %s", ref_file);
                goto error_return;
        }
 -      lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
  
 +      lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
        return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
  
   error_return:
@@@ -915,25 -912,33 +915,33 @@@ static int repack_without_ref(const cha
        return commit_lock_file(&packlock);
  }
  
- int delete_ref(const char *refname, const unsigned char *sha1)
+ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
  {
        struct ref_lock *lock;
-       int err, i, ret = 0, flag = 0;
+       int err, i = 0, ret = 0, flag = 0;
  
        lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
        if (!lock)
                return 1;
-       if (!(flag & REF_ISPACKED)) {
+       if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
                /* loose */
-               i = strlen(lock->lk->filename) - 5; /* .lock */
-               lock->lk->filename[i] = 0;
-               err = unlink(lock->lk->filename);
+               const char *path;
+               if (!(delopt & REF_NODEREF)) {
+                       i = strlen(lock->lk->filename) - 5; /* .lock */
+                       lock->lk->filename[i] = 0;
+                       path = lock->lk->filename;
+               } else {
+                       path = git_path(refname);
+               }
+               err = unlink(path);
                if (err && errno != ENOENT) {
                        ret = 1;
                        error("unlink(%s) failed: %s",
-                             lock->lk->filename, strerror(errno));
+                             path, strerror(errno));
                }
-               lock->lk->filename[i] = '.';
+               if (!(delopt & REF_NODEREF))
+                       lock->lk->filename[i] = '.';
        }
        /* removing the loose one could have resurrected an earlier
         * packed one.  Also, if it was not loose we need to repack
@@@ -958,11 -963,16 +966,16 @@@ int rename_ref(const char *oldref, cons
        struct ref_lock *lock;
        struct stat loginfo;
        int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+       const char *symref = NULL;
  
-       if (S_ISLNK(loginfo.st_mode))
+       if (log && S_ISLNK(loginfo.st_mode))
                return error("reflog for %s is a symlink", oldref);
  
-       if (!resolve_ref(oldref, orig_sha1, 1, &flag))
+       symref = resolve_ref(oldref, orig_sha1, 1, &flag);
+       if (flag & REF_ISSYMREF)
+               return error("refname %s is a symbolic ref, renaming it is not supported",
+                       oldref);
+       if (!symref)
                return error("refname %s not found", oldref);
  
        if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
                return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
                        oldref, strerror(errno));
  
-       if (delete_ref(oldref, orig_sha1)) {
+       if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
                error("unable to delete old %s", oldref);
                goto rollback;
        }
  
-       if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
+       if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1, REF_NODEREF)) {
                if (errno==EISDIR) {
                        if (remove_empty_directories(git_path("%s", newref))) {
                                error("Directory not empty: %s", newref);
                error("unable to lock %s for update", newref);
                goto rollback;
        }
        lock->force_write = 1;
        hashcpy(lock->old_sha1, orig_sha1);
        if (write_ref_sha1(lock, orig_sha1, logmsg)) {