summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorRonnie Sahlberg <sahlberg@google.com>2014-07-15 19:59:36 (GMT)
committerJunio C Hamano <gitster@pobox.com>2014-10-15 17:47:24 (GMT)
commit7695d118e5a3c9c6fcb4cb15eb766a1c57422aed (patch)
tree53872b12d57c9f7fca48379262baff5d4f4051eb /refs.c
parentaae383db8c384dc46abe199899235f67c838e601 (diff)
downloadgit-7695d118e5a3c9c6fcb4cb15eb766a1c57422aed.zip
git-7695d118e5a3c9c6fcb4cb15eb766a1c57422aed.tar.gz
git-7695d118e5a3c9c6fcb4cb15eb766a1c57422aed.tar.bz2
refs.c: change resolve_ref_unsafe reading argument to be a flags field
resolve_ref_unsafe takes a boolean argument for reading (a nonexistent ref resolves successfully for writing but not for reading). Change this to be a flags field instead, and pass the new constant RESOLVE_REF_READING when we want this behaviour. While at it, swap two of the arguments in the function to put output arguments at the end. As a nice side effect, this ensures that we can catch callers that were unaware of the new API so they can be audited. Give the wrapper functions resolve_refdup and read_ref_full the same treatment for consistency. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c93
1 files changed, 53 insertions, 40 deletions
diff --git a/refs.c b/refs.c
index 6b4236a..f8d59ab 100644
--- a/refs.c
+++ b/refs.c
@@ -1251,7 +1251,9 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
hashclr(sha1);
flag |= REF_ISBROKEN;
}
- } else if (read_ref_full(refname.buf, sha1, 1, &flag)) {
+ } else if (read_ref_full(refname.buf,
+ RESOLVE_REF_READING,
+ sha1, &flag)) {
hashclr(sha1);
flag |= REF_ISBROKEN;
}
@@ -1376,9 +1378,9 @@ static struct ref_entry *get_packed_ref(const char *refname)
* options are forwarded from resolve_safe_unsafe().
*/
static const char *handle_missing_loose_ref(const char *refname,
+ int resolve_flags,
unsigned char *sha1,
- int reading,
- int *flag)
+ int *flags)
{
struct ref_entry *entry;
@@ -1389,12 +1391,12 @@ static const char *handle_missing_loose_ref(const char *refname,
entry = get_packed_ref(refname);
if (entry) {
hashcpy(sha1, entry->u.value.sha1);
- if (flag)
- *flag |= REF_ISPACKED;
+ if (flags)
+ *flags |= REF_ISPACKED;
return refname;
}
/* The reference is not a packed reference, either. */
- if (reading) {
+ if (resolve_flags & RESOLVE_REF_READING) {
return NULL;
} else {
hashclr(sha1);
@@ -1403,21 +1405,20 @@ static const char *handle_missing_loose_ref(const char *refname,
}
/* This function needs to return a meaningful errno on failure */
-const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int reading, int *flag)
+const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
{
int depth = MAXDEPTH;
ssize_t len;
char buffer[256];
static char refname_buffer[256];
- if (flag)
- *flag = 0;
+ if (flags)
+ *flags = 0;
if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
errno = EINVAL;
return NULL;
}
-
for (;;) {
char path[PATH_MAX];
struct stat st;
@@ -1443,8 +1444,8 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea
stat_ref:
if (lstat(path, &st) < 0) {
if (errno == ENOENT)
- return handle_missing_loose_ref(refname, sha1,
- reading, flag);
+ return handle_missing_loose_ref(refname,
+ resolve_flags, sha1, flags);
else
return NULL;
}
@@ -1464,8 +1465,8 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea
!check_refname_format(buffer, 0)) {
strcpy(refname_buffer, buffer);
refname = refname_buffer;
- if (flag)
- *flag |= REF_ISSYMREF;
+ if (flags)
+ *flags |= REF_ISSYMREF;
continue;
}
}
@@ -1510,21 +1511,21 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea
*/
if (get_sha1_hex(buffer, sha1) ||
(buffer[40] != '\0' && !isspace(buffer[40]))) {
- if (flag)
- *flag |= REF_ISBROKEN;
+ if (flags)
+ *flags |= REF_ISBROKEN;
errno = EINVAL;
return NULL;
}
return refname;
}
- if (flag)
- *flag |= REF_ISSYMREF;
+ if (flags)
+ *flags |= REF_ISSYMREF;
buf = buffer + 4;
while (isspace(*buf))
buf++;
if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
- if (flag)
- *flag |= REF_ISBROKEN;
+ if (flags)
+ *flags |= REF_ISBROKEN;
errno = EINVAL;
return NULL;
}
@@ -1532,9 +1533,9 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea
}
}
-char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag)
+char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags)
{
- const char *ret = resolve_ref_unsafe(ref, sha1, reading, flag);
+ const char *ret = resolve_ref_unsafe(ref, resolve_flags, sha1, flags);
return ret ? xstrdup(ret) : NULL;
}
@@ -1545,22 +1546,22 @@ struct ref_filter {
void *cb_data;
};
-int read_ref_full(const char *refname, unsigned char *sha1, int reading, int *flags)
+int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
{
- if (resolve_ref_unsafe(refname, sha1, reading, flags))
+ if (resolve_ref_unsafe(refname, resolve_flags, sha1, flags))
return 0;
return -1;
}
int read_ref(const char *refname, unsigned char *sha1)
{
- return read_ref_full(refname, sha1, 1, NULL);
+ return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
}
int ref_exists(const char *refname)
{
unsigned char sha1[20];
- return !!resolve_ref_unsafe(refname, sha1, 1, NULL);
+ return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
}
static int filter_refs(const char *refname, const unsigned char *sha1, int flags,
@@ -1673,7 +1674,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
return 0;
}
- if (read_ref_full(refname, base, 1, &flag))
+ if (read_ref_full(refname, RESOLVE_REF_READING, base, &flag))
return -1;
/*
@@ -1714,7 +1715,7 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
if (!(flags & REF_ISSYMREF))
return 0;
- resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
+ resolves_to = resolve_ref_unsafe(refname, 0, junk, NULL);
if (!resolves_to
|| (d->refname
? strcmp(resolves_to, d->refname)
@@ -1839,7 +1840,7 @@ static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
return 0;
}
- if (!read_ref_full("HEAD", sha1, 1, &flag))
+ if (!read_ref_full("HEAD", RESOLVE_REF_READING, sha1, &flag))
return fn("HEAD", sha1, flag, cb_data);
return 0;
@@ -1919,7 +1920,7 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data)
int flag;
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
- if (!read_ref_full(buf.buf, sha1, 1, &flag))
+ if (!read_ref_full(buf.buf, RESOLVE_REF_READING, sha1, &flag))
ret = fn(buf.buf, sha1, flag, cb_data);
strbuf_release(&buf);
@@ -2014,7 +2015,9 @@ int refname_match(const char *abbrev_name, const char *full_name)
static struct ref_lock *verify_lock(struct ref_lock *lock,
const unsigned char *old_sha1, int mustexist)
{
- if (read_ref_full(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
+ if (read_ref_full(lock->ref_name,
+ mustexist ? RESOLVE_REF_READING : 0,
+ lock->old_sha1, NULL)) {
int save_errno = errno;
error("Can't verify ref %s", lock->ref_name);
unlock_ref(lock);
@@ -2087,7 +2090,8 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
this_result = refs_found ? sha1_from_ref : sha1;
mksnpath(fullref, sizeof(fullref), *p, len, str);
- r = resolve_ref_unsafe(fullref, this_result, 1, &flag);
+ r = resolve_ref_unsafe(fullref, RESOLVE_REF_READING,
+ this_result, &flag);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
@@ -2116,7 +2120,8 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
const char *ref, *it;
mksnpath(path, sizeof(path), *p, len, str);
- ref = resolve_ref_unsafe(path, hash, 1, NULL);
+ ref = resolve_ref_unsafe(path, RESOLVE_REF_READING,
+ hash, NULL);
if (!ref)
continue;
if (reflog_exists(path))
@@ -2151,6 +2156,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
int last_errno = 0;
int type, lflags;
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
+ int resolve_flags = 0;
int missing = 0;
int attempts_remaining = 3;
@@ -2162,7 +2168,11 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
lock = xcalloc(1, sizeof(struct ref_lock));
lock->lock_fd = -1;
- refname = resolve_ref_unsafe(refname, lock->old_sha1, mustexist, &type);
+ if (mustexist)
+ resolve_flags |= RESOLVE_REF_READING;
+
+ refname = resolve_ref_unsafe(refname, resolve_flags,
+ lock->old_sha1, &type);
if (!refname && errno == EISDIR) {
/* we are trying to lock foo but we used to
* have foo/bar which now does not exist;
@@ -2175,7 +2185,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
error("there are still refs under '%s'", orig_refname);
goto error_return;
}
- refname = resolve_ref_unsafe(orig_refname, lock->old_sha1, mustexist, &type);
+ refname = resolve_ref_unsafe(orig_refname, resolve_flags,
+ lock->old_sha1, &type);
}
if (type_p)
*type_p = type;
@@ -2517,7 +2528,7 @@ static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data)
unsigned char sha1[20];
int flags;
- if (read_ref_full(entry->name, sha1, 0, &flags))
+ if (read_ref_full(entry->name, 0, sha1, &flags))
/* We should at least have found the packed ref. */
die("Internal error");
if ((flags & REF_ISSYMREF) || !(flags & REF_ISPACKED)) {
@@ -2721,7 +2732,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (log && S_ISLNK(loginfo.st_mode))
return error("reflog for %s is a symlink", oldrefname);
- symref = resolve_ref_unsafe(oldrefname, orig_sha1, 1, &flag);
+ symref = resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING,
+ orig_sha1, &flag);
if (flag & REF_ISSYMREF)
return error("refname %s is a symbolic ref, renaming it is not supported",
oldrefname);
@@ -2740,7 +2752,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
goto rollback;
}
- if (!read_ref_full(newrefname, sha1, 1, NULL) &&
+ if (!read_ref_full(newrefname, RESOLVE_REF_READING, sha1, NULL) &&
delete_ref(newrefname, sha1, REF_NODEREF)) {
if (errno==EISDIR) {
if (remove_empty_directories(git_path("%s", newrefname))) {
@@ -3018,7 +3030,8 @@ static int write_ref_sha1(struct ref_lock *lock,
unsigned char head_sha1[20];
int head_flag;
const char *head_ref;
- head_ref = resolve_ref_unsafe("HEAD", head_sha1, 1, &head_flag);
+ head_ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+ head_sha1, &head_flag);
if (head_ref && (head_flag & REF_ISSYMREF) &&
!strcmp(head_ref, lock->ref_name))
log_ref_write("HEAD", lock->old_sha1, sha1, logmsg);
@@ -3389,7 +3402,7 @@ static int do_for_each_reflog(struct strbuf *name, each_ref_fn fn, void *cb_data
retval = do_for_each_reflog(name, fn, cb_data);
} else {
unsigned char sha1[20];
- if (read_ref_full(name->buf, sha1, 0, NULL))
+ if (read_ref_full(name->buf, 0, sha1, NULL))
retval = error("bad ref for %s", name->buf);
else
retval = fn(name->buf, sha1, 0, cb_data);