From: Junio C Hamano Date: Tue, 25 Aug 2015 21:57:08 +0000 (-0700) Subject: Merge branch 'dt/refs-pseudo' X-Git-Tag: v2.6.0-rc0~48 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=080cc646637f20494138c62fe6b8b0fee8d521fa;p=git Merge branch 'dt/refs-pseudo' To prepare for allowing a different "ref" backend to be plugged in to the system, update_ref()/delete_ref() have been taught about ref-like things like MERGE_HEAD that are per-worktree (they will always be written to the filesystem inside $GIT_DIR). * dt/refs-pseudo: pseudoref: check return values from read_ref() sequencer: replace write_cherry_pick_head with update_ref bisect: use update_ref pseudorefs: create and use pseudoref update and delete functions refs: add ref_type function refs: introduce pseudoref and per-worktree ref concepts --- 080cc646637f20494138c62fe6b8b0fee8d521fa diff --cc bisect.c index f9da9d1346,7eaa37a929..041a13d093 --- a/bisect.c +++ b/bisect.c @@@ -19,11 -19,7 +19,10 @@@ static struct object_id *current_bad_oi static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL}; static const char *argv_show_branch[] = {"show-branch", NULL, NULL}; - static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL}; +static const char *term_bad; +static const char *term_good; + /* Remember to update object flag allocation in object.h */ #define COUNTED (1u<<16) @@@ -951,9 -884,7 +932,8 @@@ int bisect_next_all(const char *prefix struct commit_list *tried; int reaches = 0, all = 0, nr, steps; const unsigned char *bisect_rev; - char bisect_rev_hex[GIT_SHA1_HEXSZ + 1]; + read_bisect_terms(&term_bad, &term_good); if (read_bisect_refs()) die("reading bisect refs failed"); @@@ -992,9 -921,7 +972,8 @@@ if (!hashcmp(bisect_rev, current_bad_oid->hash)) { exit_if_skipped_commits(tried, current_bad_oid); - printf("%s is the first %s commit\n", bisect_rev_hex, - printf("%s is the first bad commit\n", sha1_to_hex(bisect_rev)); ++ printf("%s is the first %s commit\n", sha1_to_hex(bisect_rev), + term_bad); show_diff_tree(prefix, revs.commits->item); /* This means the bisection process succeeded. */ exit(10); diff --cc refs.c index 835801905b,1db3654b8e..b0e0fe560c --- a/refs.c +++ b/refs.c @@@ -2854,15 -2821,120 +2854,120 @@@ static int delete_ref_loose(struct ref_ return 0; } + static int is_per_worktree_ref(const char *refname) + { + return !strcmp(refname, "HEAD"); + } + + static int is_pseudoref_syntax(const char *refname) + { + const char *c; + + for (c = refname; *c; c++) { + if (!isupper(*c) && *c != '-' && *c != '_') + return 0; + } + + return 1; + } + + enum ref_type ref_type(const char *refname) + { + if (is_per_worktree_ref(refname)) + return REF_TYPE_PER_WORKTREE; + if (is_pseudoref_syntax(refname)) + return REF_TYPE_PSEUDOREF; + return REF_TYPE_NORMAL; + } + + static int write_pseudoref(const char *pseudoref, const unsigned char *sha1, + const unsigned char *old_sha1, struct strbuf *err) + { + const char *filename; + int fd; + static struct lock_file lock; + struct strbuf buf = STRBUF_INIT; + int ret = -1; + + strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1)); + + filename = git_path("%s", pseudoref); + fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR); + if (fd < 0) { + strbuf_addf(err, "Could not open '%s' for writing: %s", + filename, strerror(errno)); + return -1; + } + + if (old_sha1) { + unsigned char actual_old_sha1[20]; + + if (read_ref(pseudoref, actual_old_sha1)) + die("could not read ref '%s'", pseudoref); + if (hashcmp(actual_old_sha1, old_sha1)) { + strbuf_addf(err, "Unexpected sha1 when writing %s", pseudoref); + rollback_lock_file(&lock); + goto done; + } + } + + if (write_in_full(fd, buf.buf, buf.len) != buf.len) { + strbuf_addf(err, "Could not write to '%s'", filename); + rollback_lock_file(&lock); + goto done; + } + + commit_lock_file(&lock); + ret = 0; + done: + strbuf_release(&buf); + return ret; + } + + static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1) + { + static struct lock_file lock; + const char *filename; + + filename = git_path("%s", pseudoref); + + if (old_sha1 && !is_null_sha1(old_sha1)) { + int fd; + unsigned char actual_old_sha1[20]; + + fd = hold_lock_file_for_update(&lock, filename, + LOCK_DIE_ON_ERROR); + if (fd < 0) + die_errno(_("Could not open '%s' for writing"), filename); + if (read_ref(pseudoref, actual_old_sha1)) + die("could not read ref '%s'", pseudoref); + if (hashcmp(actual_old_sha1, old_sha1)) { + warning("Unexpected sha1 when deleting %s", pseudoref); + rollback_lock_file(&lock); + return -1; + } + + unlink(filename); + rollback_lock_file(&lock); + } else { + unlink(filename); + } + + return 0; + } + -int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flags) +int delete_ref(const char *refname, const unsigned char *old_sha1, + unsigned int flags) { struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; + if (ref_type(refname) == REF_TYPE_PSEUDOREF) - return delete_pseudoref(refname, sha1); ++ return delete_pseudoref(refname, old_sha1); + transaction = ref_transaction_begin(&err); if (!transaction || - ref_transaction_delete(transaction, refname, - (sha1 && !is_null_sha1(sha1)) ? sha1 : NULL, + ref_transaction_delete(transaction, refname, old_sha1, flags, NULL, &err) || ref_transaction_commit(transaction, &err)) { error("%s", err.buf); diff --cc refs.h index 6a3fa6d41d,1927bda993..e9a5f3230a --- a/refs.h +++ b/refs.h @@@ -442,9 -378,16 +442,17 @@@ int update_ref(const char *msg, const c unsigned int flags, enum action_on_err onerr); extern int parse_hide_refs_config(const char *var, const char *value, const char *); + extern int ref_is_hidden(const char *); + enum ref_type { + REF_TYPE_PER_WORKTREE, + REF_TYPE_PSEUDOREF, + REF_TYPE_NORMAL, + }; + + enum ref_type ref_type(const char *refname); + enum expire_reflog_flags { EXPIRE_REFLOGS_DRY_RUN = 1 << 0, EXPIRE_REFLOGS_UPDATE_REF = 1 << 1,