From: Junio C Hamano Date: Mon, 29 Sep 2014 19:36:10 +0000 (-0700) Subject: Merge branch 'da/rev-parse-verify-quiet' X-Git-Tag: v2.2.0-rc0~77 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/507fe835ed0753ff266fdb998853cc5dea3758c6?hp=-c Merge branch 'da/rev-parse-verify-quiet' "rev-parse --verify --quiet $name" is meant to quietly exit with a non-zero status when $name is not a valid object name, but still gave error messages in some cases. * da/rev-parse-verify-quiet: stash: prefer --quiet over shell redirection of the standard error stream refs: make rev-parse --quiet actually quiet t1503: use test_must_be_empty Documentation: a note about stdout for git rev-parse --verify --quiet --- 507fe835ed0753ff266fdb998853cc5dea3758c6 diff --combined builtin/show-branch.c index a1275237ee,46498e1113..199b081e9b --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@@ -563,7 -563,7 +563,7 @@@ static int git_show_branch_config(cons default_arg[default_num++] = "show-branch"; } else if (default_alloc <= default_num + 1) { default_alloc = default_alloc * 3 / 2 + 20; - default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc); + REALLOC_ARRAY(default_arg, default_alloc); } default_arg[default_num++] = xstrdup(value); default_arg[default_num] = NULL; @@@ -723,6 -723,7 +723,7 @@@ int cmd_show_branch(int ac, const char char nth_desc[256]; char *ref; int base = 0; + unsigned int flags = 0; if (ac == 0) { static const char *fake_av[2]; @@@ -749,7 -750,7 +750,7 @@@ /* Ah, that is a date spec... */ unsigned long at; at = approxidate(reflog_base); - read_ref_at(ref, at, -1, sha1, NULL, + read_ref_at(ref, flags, at, -1, sha1, NULL, NULL, NULL, &base); } } @@@ -760,7 -761,7 +761,7 @@@ unsigned long timestamp; int tz; - if (read_ref_at(ref, 0, base+i, sha1, &logmsg, + if (read_ref_at(ref, flags, 0, base+i, sha1, &logmsg, ×tamp, &tz, NULL)) { reflog = i; break; diff --combined git-stash.sh index 0158c73386,7ece0f1420..d4cf818be9 --- a/git-stash.sh +++ b/git-stash.sh @@@ -50,7 -50,7 +50,7 @@@ clear_stash () then die "$(gettext "git stash clear with parameters is unimplemented")" fi - if current=$(git rev-parse --verify $ref_stash 2>/dev/null) + if current=$(git rev-parse --verify --quiet $ref_stash) then git update-ref -d $ref_stash $current fi @@@ -292,7 -292,7 +292,7 @@@ save_stash () } have_stash () { - git rev-parse --verify $ref_stash >/dev/null 2>&1 + git rev-parse --verify --quiet $ref_stash >/dev/null } list_stash () { @@@ -392,12 -392,12 +392,12 @@@ parse_flags_and_rev( ;; esac - REV=$(git rev-parse --quiet --symbolic --verify "$1" 2>/dev/null) || { + REV=$(git rev-parse --symbolic --verify --quiet "$1") || { reference="$1" - die "$(eval_gettext "\$reference is not valid reference")" + die "$(eval_gettext "\$reference is not a valid reference")" } - i_commit=$(git rev-parse --quiet --verify "$REV^2" 2>/dev/null) && + i_commit=$(git rev-parse --verify --quiet "$REV^2") && set -- $(git rev-parse "$REV" "$REV^1" "$REV:" "$REV^1:" "$REV^2:" 2>/dev/null) && s=$1 && w_commit=$1 && @@@ -409,7 -409,7 +409,7 @@@ test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" && IS_STASH_REF=t - u_commit=$(git rev-parse --quiet --verify "$REV^3" 2>/dev/null) && + u_commit=$(git rev-parse --verify --quiet "$REV^3") && u_tree=$(git rev-parse "$REV^3:" 2>/dev/null) } @@@ -531,7 -531,8 +531,8 @@@ drop_stash () die "$(eval_gettext "\${REV}: Could not drop stash entry")" # clear_stash if we just dropped the last stash entry - git rev-parse --verify "$ref_stash@{0}" >/dev/null 2>&1 || clear_stash + git rev-parse --verify --quiet "$ref_stash@{0}" >/dev/null || + clear_stash } apply_to_branch () { diff --combined refs.c index 311a6b52b1,9e405f9e41..ffd45e9292 --- a/refs.c +++ b/refs.c @@@ -784,32 -784,37 +784,32 @@@ static void prime_ref_dir(struct ref_di prime_ref_dir(get_ref_dir(entry)); } } -/* - * Return true iff refname1 and refname2 conflict with each other. - * Two reference names conflict if one of them exactly matches the - * leading components of the other; e.g., "foo/bar" conflicts with - * both "foo" and with "foo/bar/baz" but not with "foo/bar" or - * "foo/barbados". - */ -static int names_conflict(const char *refname1, const char *refname2) + +static int entry_matches(struct ref_entry *entry, const char *refname) { - for (; *refname1 && *refname1 == *refname2; refname1++, refname2++) - ; - return (*refname1 == '\0' && *refname2 == '/') - || (*refname1 == '/' && *refname2 == '\0'); + return refname && !strcmp(entry->name, refname); } -struct name_conflict_cb { - const char *refname; - const char *oldrefname; - const char *conflicting_refname; +struct nonmatching_ref_data { + const char *skip; + struct ref_entry *found; }; -static int name_conflict_fn(struct ref_entry *entry, void *cb_data) +static int nonmatching_ref_fn(struct ref_entry *entry, void *vdata) { - struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data; - if (data->oldrefname && !strcmp(data->oldrefname, entry->name)) + struct nonmatching_ref_data *data = vdata; + + if (entry_matches(entry, data->skip)) return 0; - if (names_conflict(data->refname, entry->name)) { - data->conflicting_refname = entry->name; - return 1; - } - return 0; + + data->found = entry; + return 1; +} + +static void report_refname_conflict(struct ref_entry *entry, + const char *refname) +{ + error("'%s' exists; cannot create '%s'", entry->name, refname); } /* @@@ -818,84 -823,21 +818,84 @@@ * oldrefname is non-NULL, ignore potential conflicts with oldrefname * (e.g., because oldrefname is scheduled for deletion in the same * operation). + * + * Two reference names conflict if one of them exactly matches the + * leading components of the other; e.g., "foo/bar" conflicts with + * both "foo" and with "foo/bar/baz" but not with "foo/bar" or + * "foo/barbados". */ static int is_refname_available(const char *refname, const char *oldrefname, struct ref_dir *dir) { - struct name_conflict_cb data; - data.refname = refname; - data.oldrefname = oldrefname; - data.conflicting_refname = NULL; + const char *slash; + size_t len; + int pos; + char *dirname; - sort_ref_dir(dir); - if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, &data)) { - error("'%s' exists; cannot create '%s'", - data.conflicting_refname, refname); + for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { + /* + * We are still at a leading dir of the refname; we are + * looking for a conflict with a leaf entry. + * + * If we find one, we still must make sure it is + * not "oldrefname". + */ + pos = search_ref_dir(dir, refname, slash - refname); + if (pos >= 0) { + struct ref_entry *entry = dir->entries[pos]; + if (entry_matches(entry, oldrefname)) + return 1; + report_refname_conflict(entry, refname); + return 0; + } + + + /* + * Otherwise, we can try to continue our search with + * the next component; if we come up empty, we know + * there is nothing under this whole prefix. + */ + pos = search_ref_dir(dir, refname, slash + 1 - refname); + if (pos < 0) + return 1; + + dir = get_ref_dir(dir->entries[pos]); + } + + /* + * We are at the leaf of our refname; we want to + * make sure there are no directories which match it. + */ + len = strlen(refname); + dirname = xmallocz(len + 1); + sprintf(dirname, "%s/", refname); + pos = search_ref_dir(dir, dirname, len + 1); + free(dirname); + + if (pos >= 0) { + /* + * We found a directory named "refname". It is a + * problem iff it contains any ref that is not + * "oldrefname". + */ + struct ref_entry *entry = dir->entries[pos]; + struct ref_dir *dir = get_ref_dir(entry); + struct nonmatching_ref_data data; + + data.skip = oldrefname; + sort_ref_dir(dir); + if (!do_for_each_entry_in_dir(dir, 0, nonmatching_ref_fn, &data)) + return 1; + + report_refname_conflict(data.found, refname); return 0; } + + /* + * There is no point in searching for another leaf + * node which matches it; such an entry would be the + * ref we are looking for, not a conflict. + */ return 1; } @@@ -2248,12 -2190,25 +2248,12 @@@ struct ref_lock *lock_any_ref_for_updat * Write an entry to the packed-refs file for the specified refname. * If peeled is non-NULL, write it as the entry's peeled value. */ -static void write_packed_entry(int fd, char *refname, unsigned char *sha1, +static void write_packed_entry(FILE *fh, char *refname, unsigned char *sha1, unsigned char *peeled) { - char line[PATH_MAX + 100]; - int len; - - len = snprintf(line, sizeof(line), "%s %s\n", - sha1_to_hex(sha1), refname); - /* this should not happen but just being defensive */ - if (len > sizeof(line)) - die("too long a refname '%s'", refname); - write_or_die(fd, line, len); - - if (peeled) { - if (snprintf(line, sizeof(line), "^%s\n", - sha1_to_hex(peeled)) != PEELED_LINE_LENGTH) - die("internal error"); - write_or_die(fd, line, PEELED_LINE_LENGTH); - } + fprintf_or_die(fh, "%s %s\n", sha1_to_hex(sha1), refname); + if (peeled) + fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled)); } /* @@@ -2261,12 -2216,13 +2261,12 @@@ */ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data) { - int *fd = cb_data; enum peel_status peel_status = peel_entry(entry, 0); if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG) error("internal error: %s is not a valid packed reference!", entry->name); - write_packed_entry(*fd, entry->name, entry->u.value.sha1, + write_packed_entry(cb_data, entry->name, entry->u.value.sha1, peel_status == PEEL_PEELED ? entry->u.value.peeled : NULL); return 0; @@@ -2302,22 -2258,15 +2302,22 @@@ int commit_packed_refs(void get_packed_ref_cache(&ref_cache); int error = 0; int save_errno = 0; + FILE *out; if (!packed_ref_cache->lock) die("internal error: packed-refs not locked"); - write_or_die(packed_ref_cache->lock->fd, - PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER)); + out = fdopen(packed_ref_cache->lock->fd, "w"); + if (!out) + die_errno("unable to fdopen packed-refs descriptor"); + + fprintf_or_die(out, "%s", PACKED_REFS_HEADER); do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache), - 0, write_packed_entry_fn, - &packed_ref_cache->lock->fd); + 0, write_packed_entry_fn, out); + if (fclose(out)) + die_errno("write error"); + packed_ref_cache->lock->fd = -1; + if (commit_lock_file(packed_ref_cache->lock)) { save_errno = errno; error = -1; @@@ -3159,7 -3108,7 +3159,7 @@@ static int read_ref_at_ent_oldest(unsig return 1; } - int read_ref_at(const char *refname, unsigned long at_time, int cnt, + int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt) { @@@ -3177,8 -3126,12 +3177,12 @@@ for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb); - if (!cb.reccnt) - die("Log for %s is empty.", refname); + if (!cb.reccnt) { + if (flags & GET_SHA1_QUIETLY) + exit(128); + else + die("Log for %s is empty.", refname); + } if (cb.found_it) return 0; diff --combined refs.h index 10fc3a2634,0ca60599b1..2328f06e77 --- a/refs.h +++ b/refs.h @@@ -109,7 -109,7 +109,7 @@@ static inline const char *has_glob_spec extern int for_each_rawref(each_ref_fn, void *); extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname); -extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list* refnames); +extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames); /* * Lock the packed-refs file for writing. Flags is passed to @@@ -206,7 -206,8 +206,8 @@@ extern int write_ref_sha1(struct ref_lo int log_ref_setup(const char *refname, char *logfile, int bufsize); /** Reads log for the value of ref during at_time. **/ - extern int read_ref_at(const char *refname, unsigned long at_time, int cnt, + extern int read_ref_at(const char *refname, unsigned int flags, + unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);