From 691f1a28bf57618d8b44a193b1d28013c858aba6 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Wed, 29 Apr 2009 23:22:56 +0200 Subject: replace direct calls to unlink(2) with unlink_or_warn This helps to notice when something's going wrong, especially on systems which lock open files. I used the following criteria when selecting the code for replacement: - it was already printing a warning for the unlink failures - it is in a function which already printing something or is called from such a function - it is in a static function, returning void and the function is only called from a builtin main function (cmd_) - it is in a function which handles emergency exit (signal handlers) - it is in a function which is obvously cleaning up the lockfiles Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- refs.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index e65a3b4c4e..2b1f0f0e6e 100644 --- a/refs.c +++ b/refs.c @@ -1002,12 +1002,10 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) } else { path = git_path("%s", refname); } - err = unlink(path); - if (err && errno != ENOENT) { + err = unlink_or_warn(path); + if (err && errno != ENOENT) ret = 1; - error("unlink(%s) failed: %s", - path, strerror(errno)); - } + if (!(delopt & REF_NODEREF)) lock->lk->filename[i] = '.'; } @@ -1017,10 +1015,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) */ ret |= repack_without_ref(refname); - err = unlink(git_path("logs/%s", lock->ref_name)); - if (err && errno != ENOENT) - warning("unlink(%s) failed: %s", - git_path("logs/%s", lock->ref_name), strerror(errno)); + unlink_or_warn(git_path("logs/%s", lock->ref_name)); invalidate_cached_refs(); unlock_ref(lock); return ret; @@ -1381,7 +1376,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master, if (adjust_shared_perm(git_HEAD)) { error("Unable to fix permissions on %s", lockpath); error_unlink_return: - unlink(lockpath); + unlink_or_warn(lockpath); error_free_return: free(git_HEAD); return -1; -- cgit v1.2.1 From a4c2e69936df8dd0b071b85664c6cc6a4870dd84 Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Fri, 8 May 2009 07:32:37 +0200 Subject: Disallow '\' in ref names This is asking for trouble since '\' is a directory separator in Windows and thus may produce unpredictable results. Signed-off-by: Robin Rosenberg Signed-off-by: Junio C Hamano --- refs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index e65a3b4c4e..fc33bc6ac4 100644 --- a/refs.c +++ b/refs.c @@ -682,12 +682,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data) * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or * - it ends with a "/". * - it ends with ".lock" + * - it contains a "\" (backslash) */ static inline int bad_ref_char(int ch) { if (((unsigned) ch) <= ' ' || - ch == '~' || ch == '^' || ch == ':') + ch == '~' || ch == '^' || ch == ':' || ch == '\\') return 1; /* 2.13 Pattern Matching Notation */ if (ch == '?' || ch == '[') /* Unsupported */ -- cgit v1.2.1 From 4577e483648f50dd80faa401dc1d3eb33ffb627b Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Thu, 14 May 2009 00:22:04 +0300 Subject: Change prettify_ref to prettify_refname In preparation to be used when the ref object is not available Signed-off-by: Felipe Contreras Acked-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index e65a3b4c4e..e74461eaaf 100644 --- a/refs.c +++ b/refs.c @@ -750,9 +750,8 @@ int check_ref_format(const char *ref) } } -const char *prettify_ref(const struct ref *ref) +const char *prettify_refname(const char *name) { - const char *name = ref->name; return name + ( !prefixcmp(name, "refs/heads/") ? 11 : !prefixcmp(name, "refs/tags/") ? 10 : -- cgit v1.2.1 From f475e08edbbabe38bd758fd42f08f646551468d9 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 25 May 2009 06:37:15 -0400 Subject: lock_ref: inform callers of unavailable ref One of the ways that locking might fail is that there is a DF conflict between two refs (e.g., you want to lock "foo/bar" but "foo" already exists). In this case, we return an error, but there is no way for the caller to know the specific problem. This patch sets errno to ENOTDIR, which is the most sensible code. It's what we would see if the refs were stored purely in the filesystem (but these days we must check the namespace manually due to packed refs). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index e65a3b4c4e..8679c17e0d 100644 --- a/refs.c +++ b/refs.c @@ -893,8 +893,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char * name is a proper prefix of our refname. */ if (missing && - !is_refname_available(ref, NULL, get_packed_refs(), 0)) + !is_refname_available(ref, NULL, get_packed_refs(), 0)) { + last_errno = ENOTDIR; goto error_return; + } lock->lk = xcalloc(1, sizeof(struct lock_file)); -- cgit v1.2.1 From 292687003abcfb68d296c57d7e812b0469f74647 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 23 Jan 2009 10:06:38 +0100 Subject: refs: add a "for_each_replace_ref" function This is some preparation work for the following patches that are using the "refs/replace/" ref namespace. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- refs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 24438c652f..6a136512c7 100644 --- a/refs.c +++ b/refs.c @@ -667,6 +667,11 @@ int for_each_remote_ref(each_ref_fn fn, void *cb_data) return for_each_ref_in("refs/remotes/", fn, cb_data); } +int for_each_replace_ref(each_ref_fn fn, void *cb_data) +{ + return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data); +} + int for_each_rawref(each_ref_fn fn, void *cb_data) { return do_for_each_ref("refs/", fn, 0, -- cgit v1.2.1 From d824cbba02a4061400a0e382f9bd241fbbff34f0 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 27 Jun 2009 17:58:46 +0200 Subject: Convert existing die(..., strerror(errno)) to die_errno() Change calls to die(..., strerror(errno)) to use the new die_errno(). In the process, also make slight style adjustments: at least state _something_ about the function that failed (instead of just printing the pathname), and put paths in single quotes. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 24438c652f..dffe395a97 100644 --- a/refs.c +++ b/refs.c @@ -1418,7 +1418,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * logfile = git_path("logs/%s", ref); logfd = open(logfile, O_RDONLY, 0); if (logfd < 0) - die("Unable to read log %s: %s", logfile, strerror(errno)); + die_errno("Unable to read log '%s'", logfile); fstat(logfd, &st); if (!st.st_size) die("Log %s is empty.", logfile); -- cgit v1.2.1 From 9d33f7c22fda81f7be8a7aa1576e6d399d3b45ec Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 16 Jul 2009 16:25:18 -0500 Subject: refs.c: release file descriptor on error return Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- refs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 90163bdc56..bb0762ee2b 100644 --- a/refs.c +++ b/refs.c @@ -1525,8 +1525,10 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, if (fstat(fileno(logfp), &statbuf) || statbuf.st_size < ofs || fseek(logfp, -ofs, SEEK_END) || - fgets(buf, sizeof(buf), logfp)) + fgets(buf, sizeof(buf), logfp)) { + fclose(logfp); return -1; + } } while (fgets(buf, sizeof(buf), logfp)) { -- cgit v1.2.1 From eafb45265bb9fcbee3cc03b451da7e17db9e6be7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 22 Jul 2009 23:07:05 -0700 Subject: do_one_ref(): null_sha1 check is not about broken ref f8948e2 (remote prune: warn dangling symrefs, 2009-02-08) introduced a more dangerous variant of for_each_ref() family that skips the check for dangling refs, but it also made another unrelated check optional by mistake. The check to see if a ref points at 0{40} is not about brokenness, but is about a possible future plan to represent a deleted ref by writing 40 "0" in a loose ref when there is a stale version of the same ref already in .git/packed-refs, so that we can implement deletion of a ref without having to rewrite the packed refs file excluding the ref being deleted. This check has to live outside of the conditional. Signed-off-by: Junio C Hamano --- refs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index bb0762ee2b..3da3c8cefc 100644 --- a/refs.c +++ b/refs.c @@ -531,9 +531,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim, { if (strncmp(base, entry->name, trim)) return 0; + /* Is this a "negative ref" that represents a deleted ref? */ + if (is_null_sha1(entry->sha1)) + return 0; if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { - if (is_null_sha1(entry->sha1)) - return 0; if (!has_sha1_file(entry->sha1)) { error("%s does not point to a valid object!", entry->name); return 0; -- cgit v1.2.1 From a0f4afbe87ddda7902e36350d163dea146166550 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 30 Jun 2009 15:33:45 -0700 Subject: clean: require double -f options to nuke nested git repository and work tree When you have an embedded git work tree in your work tree (be it an orphaned submodule, or an independent checkout of an unrelated project), "git clean -d -f" blindly descended into it and removed everything. This is rarely what the user wants. Signed-off-by: Junio C Hamano --- refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index e49eaa3089..dd9c9ba3f6 100644 --- a/refs.c +++ b/refs.c @@ -821,7 +821,7 @@ static int remove_empty_directories(const char *file) strbuf_init(&path, 20); strbuf_addstr(&path, file); - result = remove_dir_recursively(&path, 1); + result = remove_dir_recursively(&path, REMOVE_DIR_EMPTY_ONLY); strbuf_release(&path); -- cgit v1.2.1 From 1b018fd9be290fd6a70ce3093ab1dc1abce74e00 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Sun, 27 Sep 2009 01:15:09 +0200 Subject: git branch -D: give a better error message when lockfile creation fails Previously the old error message just told the user that it was not possible to delete the ref from the packed-refs file. Give instructions on how to resolve the problem. Signed-off-by: Miklos Vajna Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- refs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 24865cf5a6..808f56bb27 100644 --- a/refs.c +++ b/refs.c @@ -972,8 +972,10 @@ static int repack_without_ref(const char *refname) if (!found) return 0; fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0); - if (fd < 0) + if (fd < 0) { + unable_to_lock_error(git_path("packed-refs"), errno); return error("cannot delete '%s' from packed refs", refname); + } for (list = packed_ref_list; list; list = list->next) { char line[PATH_MAX + 100]; -- cgit v1.2.1 From 3cf6134ad016712ecb78186d9079b9cff7b25416 Mon Sep 17 00:00:00 2001 From: Jay Soffian Date: Tue, 10 Nov 2009 00:03:32 -0500 Subject: teach warn_dangling_symref to take a FILE argument Different callers of warn_dangling_symref() may want to control whether its output goes to stdout or stderr so let it take a FILE argument. Signed-off-by: Jay Soffian Signed-off-by: Junio C Hamano --- refs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 808f56bb27..3e73a0a36d 100644 --- a/refs.c +++ b/refs.c @@ -286,6 +286,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list) } struct warn_if_dangling_data { + FILE *fp; const char *refname; const char *msg_fmt; }; @@ -304,13 +305,13 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha if (!resolves_to || strcmp(resolves_to, d->refname)) return 0; - printf(d->msg_fmt, refname); + fprintf(d->fp, d->msg_fmt, refname); return 0; } -void warn_dangling_symref(const char *msg_fmt, const char *refname) +void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname) { - struct warn_if_dangling_data data = { refname, msg_fmt }; + struct warn_if_dangling_data data = { fp, refname, msg_fmt }; for_each_rawref(warn_if_dangling_symref, &data); } -- cgit v1.2.1 From d08bae7e221727e26baab984b792854b842130d7 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Wed, 20 Jan 2010 11:48:25 +0200 Subject: rev-parse --glob Add --glob= option to rev-parse and everything that accepts its options. This option matches all refs that match given shell glob pattern (complete with some DWIM logic). Example: 'git log --branches --not --glob=remotes/origin' To show what you have that origin doesn't. Signed-off-by: Ilari Liusvaara Signed-off-by: Junio C Hamano --- refs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 3e73a0a36d..34fff75b0d 100644 --- a/refs.c +++ b/refs.c @@ -519,6 +519,13 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int * return ref; } +/* The argument to filter_refs */ +struct ref_filter { + const char *pattern; + each_ref_fn *fn; + void *cb_data; +}; + int read_ref(const char *ref, unsigned char *sha1) { if (resolve_ref(ref, sha1, 1, NULL)) @@ -545,6 +552,15 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim, return fn(entry->name + trim, entry->sha1, entry->flag, cb_data); } +static int filter_refs(const char *ref, const unsigned char *sha, int flags, + void *data) +{ + struct ref_filter *filter = (struct ref_filter *)data; + if (fnmatch(filter->pattern, ref, 0)) + return 0; + return filter->fn(ref, sha, flags, filter->cb_data); +} + int peel_ref(const char *ref, unsigned char *sha1) { int flag; @@ -674,6 +690,35 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data) return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data); } +int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data) +{ + struct strbuf real_pattern = STRBUF_INIT; + struct ref_filter filter; + const char *has_glob_specials; + int ret; + + if (prefixcmp(pattern, "refs/")) + strbuf_addstr(&real_pattern, "refs/"); + strbuf_addstr(&real_pattern, pattern); + + has_glob_specials = strpbrk(pattern, "?*["); + if (!has_glob_specials) { + /* Append impiled '/' '*' if not present. */ + if (real_pattern.buf[real_pattern.len - 1] != '/') + strbuf_addch(&real_pattern, '/'); + /* No need to check for '*', there is none. */ + strbuf_addch(&real_pattern, '*'); + } + + filter.pattern = real_pattern.buf; + filter.fn = fn; + filter.cb_data = cb_data; + ret = for_each_ref(filter_refs, &filter); + + strbuf_release(&real_pattern); + return ret; +} + int for_each_rawref(each_ref_fn fn, void *cb_data) { return do_for_each_ref("refs/", fn, 0, -- cgit v1.2.1 From b09fe971dea73ff6f5296ce533a566114b23ca4e Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Wed, 20 Jan 2010 11:48:26 +0200 Subject: rev-parse --branches/--tags/--remotes=pattern Since local branch, tags and remote tracking branch namespaces are most often used, add shortcut notations for globbing those in manner similar to --glob option. With this, one can express the "what I have but origin doesn't?" as: 'git log --branches --not --remotes=origin' Original-idea-by: Johannes Sixt Signed-off-by: Ilari Liusvaara Signed-off-by: Junio C Hamano --- refs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 34fff75b0d..503a8c2bd0 100644 --- a/refs.c +++ b/refs.c @@ -690,15 +690,18 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data) return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data); } -int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data) +int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, + const char *prefix, void *cb_data) { struct strbuf real_pattern = STRBUF_INIT; struct ref_filter filter; const char *has_glob_specials; int ret; - if (prefixcmp(pattern, "refs/")) + if (!prefix && prefixcmp(pattern, "refs/")) strbuf_addstr(&real_pattern, "refs/"); + else if (prefix) + strbuf_addstr(&real_pattern, prefix); strbuf_addstr(&real_pattern, pattern); has_glob_specials = strpbrk(pattern, "?*["); @@ -719,6 +722,11 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data) return ret; } +int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data) +{ + return for_each_glob_ref_in(fn, pattern, NULL, cb_data); +} + int for_each_rawref(each_ref_fn fn, void *cb_data) { return do_for_each_ref("refs/", fn, 0, -- cgit v1.2.1 From 9517e6b84357252e1882091343661c34d978771e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 3 Feb 2010 21:23:18 -0800 Subject: Typofixes outside documentation area begining -> beginning canonicalizations -> canonicalization comand -> command dewrapping -> unwrapping dirtyness -> dirtiness DISCLAMER -> DISCLAIMER explicitely -> explicitly feeded -> fed impiled -> implied madatory -> mandatory mimick -> mimic preceeding -> preceding reqeuest -> request substition -> substitution Signed-off-by: Junio C Hamano --- refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 503a8c2bd0..f3fcbe023a 100644 --- a/refs.c +++ b/refs.c @@ -706,7 +706,7 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, has_glob_specials = strpbrk(pattern, "?*["); if (!has_glob_specials) { - /* Append impiled '/' '*' if not present. */ + /* Append implied '/' '*' if not present. */ if (real_pattern.buf[real_pattern.len - 1] != '/') strbuf_addch(&real_pattern, '/'); /* No need to check for '*', there is none. */ -- cgit v1.2.1