summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 031e6c8)
raw | patch | inline | side by side (parent: 031e6c8)
author | Miklos Vajna <vmiklos@frugalware.org> | |
Sun, 26 Oct 2008 02:33:56 +0000 (03:33 +0100) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Sun, 26 Oct 2008 21:42:57 +0000 (14:42 -0700) |
This had two problems with symrefs. First, it copied the actual sha1
instead of the "pointer", second it failed to remove the old ref after a
successful rename.
Given that till now delete_ref() always dereferenced symrefs, a new
parameters has been introduced to delete_ref() to allow deleting refs
without a dereference.
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
instead of the "pointer", second it failed to remove the old ref after a
successful rename.
Given that till now delete_ref() always dereferenced symrefs, a new
parameters has been introduced to delete_ref() to allow deleting refs
without a dereference.
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-branch.c | patch | blob | history | |
builtin-remote.c | patch | blob | history | |
builtin-reset.c | patch | blob | history | |
builtin-send-pack.c | patch | blob | history | |
builtin-tag.c | patch | blob | history | |
builtin-update-ref.c | patch | blob | history | |
cache.h | patch | blob | history | |
receive-pack.c | patch | blob | history | |
refs.c | patch | blob | history | |
t/t3200-branch.sh | patch | blob | history |
diff --git a/builtin-branch.c b/builtin-branch.c
index b1a2ad7a6b3b150cda8d031a87352a4daedc40ea..4b4abfd3639d2c6a1405e2e056ed5362b4b73abb 100644 (file)
--- a/builtin-branch.c
+++ b/builtin-branch.c
continue;
}
- if (delete_ref(name, sha1)) {
+ if (delete_ref(name, sha1, 0)) {
error("Error deleting %sbranch '%s'", remote,
argv[i]);
ret = 1;
diff --git a/builtin-remote.c b/builtin-remote.c
index 90a4e35828697f349a38ba3486c40813db32cee0..584280fbf5bbbd485a1388adb15104a1ad1cf19c 100644 (file)
--- a/builtin-remote.c
+++ b/builtin-remote.c
const char *refname = item->string;
unsigned char *sha1 = item->util;
- if (delete_ref(refname, sha1))
+ if (delete_ref(refname, sha1, 0))
result |= error("Could not remove branch %s", refname);
}
return result;
const char *refname = states.stale.items[i].util;
if (!dry_run)
- result |= delete_ref(refname, NULL);
+ result |= delete_ref(refname, NULL, 0);
printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
abbrev_ref(refname, "refs/remotes/"));
diff --git a/builtin-reset.c b/builtin-reset.c
index 16e6bb20f1af6a7a684a747b3c0cc26ceabe8ce7..9514b77f8c0b4e8a576e888df905b501e198df24 100644 (file)
--- a/builtin-reset.c
+++ b/builtin-reset.c
update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
}
else if (old_orig)
- delete_ref("ORIG_HEAD", old_orig);
+ delete_ref("ORIG_HEAD", old_orig, 0);
prepend_reflog_action("updating HEAD", msg, sizeof(msg));
update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 2af9f2934142f55858f4b5c76deb6397ac74b9f8..ea1ad6e35f59ef361b40e8f5a54bc9fc9940e59a 100644 (file)
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
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 --git a/builtin-tag.c b/builtin-tag.c
index f2853d08c77368b37b40c7ea51f5a124208d385f..5b141c584680ecc2362fc0e036e01dbeefa4ee90 100644 (file)
--- a/builtin-tag.c
+++ b/builtin-tag.c
static int delete_tag(const char *name, const char *ref,
const unsigned char *sha1)
{
- if (delete_ref(ref, sha1))
+ if (delete_ref(ref, sha1, 0))
return 1;
printf("Deleted tag '%s'\n", name);
return 0;
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 56a0b1b39cf4c4fc51dbbff256240655bc36a038..d8f3142c06c2d7c5202c9c132a12457d6e8b43a6 100644 (file)
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
die("%s: not a valid old SHA1", oldval);
if (delete)
- return delete_ref(refname, oldval ? oldsha1 : NULL);
+ return delete_ref(refname, oldval ? oldsha1 : NULL, 0);
else
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
index 884fae826cb8c296520aecbc8c23d9848dacb606..715348a0663e278d4eecc0c04c0ad9b8148493b2 100644 (file)
--- a/cache.h
+++ b/cache.h
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 --git a/receive-pack.c b/receive-pack.c
index d44c19e6b577023dcbaa188a0e67130ff4e5bd9a..f0145bd9011689b29e3aad3db5fb55cd94aacb2a 100644 (file)
--- a/receive-pack.c
+++ b/receive-pack.c
warning ("Allowing deletion of corrupt ref.");
old_sha1 = NULL;
}
- if (delete_ref(name, old_sha1)) {
+ if (delete_ref(name, old_sha1, 0)) {
error("failed to delete %s", name);
return "failed to delete";
}
index 39a3b23804d2da715c564459bf320be23d41c1bf..b929301752c3081c7d42cea8e0297e663fe500cb 100644 (file)
--- a/refs.c
+++ b/refs.c
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)) {
/* 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
struct ref_lock *lock;
struct stat loginfo;
int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+ const char *symref = NULL;
+ int is_symref = 0;
if (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)
+ is_symref = 1;
+ 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);
}
logmoved = log;
- lock = lock_ref_sha1_basic(newref, NULL, 0, NULL);
- if (!lock) {
- 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)) {
- error("unable to write current sha1 into %s", newref);
- goto rollback;
- }
+ if (!is_symref) {
+ lock = lock_ref_sha1_basic(newref, NULL, 0, NULL);
+ if (!lock) {
+ 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)) {
+ error("unable to write current sha1 into %s", newref);
+ goto rollback;
+ }
+ } else
+ create_symref(newref, symref, logmsg);
return 0;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 2147eacc5057128facc08816a2980646bed28ec5..fdeb1f529ce14d5500976c0e5683c3cbc2fa3501 100755 (executable)
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
"test $(git config branch.s.dummy) = Hello &&
test_must_fail git config branch.s/s/dummy"
+test_expect_success 'renaming a symref' \
+'
+ git symbolic-ref refs/heads/master2 refs/heads/master &&
+ git branch -m master2 master3 &&
+ git symbolic-ref refs/heads/master3 &&
+ test -f .git/refs/heads/master &&
+ ! test -f .git/refs/heads/master2
+'
+
test_expect_success \
'git branch -m u v should fail when the reflog for u is a symlink' '
git branch -l u &&