summaryrefslogtreecommitdiff
path: root/sha1_name.c
diff options
context:
space:
mode:
Diffstat (limited to 'sha1_name.c')
-rw-r--r--sha1_name.c108
1 files changed, 64 insertions, 44 deletions
diff --git a/sha1_name.c b/sha1_name.c
index 6de8c87c8a..e57513e610 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -416,12 +416,12 @@ static int ambiguous_path(const char *path, int len)
return slash;
}
-static inline int upstream_mark(const char *string, int len)
+static inline int at_mark(const char *string, int len,
+ const char **suffix, int nr)
{
- const char *suffix[] = { "@{upstream}", "@{u}" };
int i;
- for (i = 0; i < ARRAY_SIZE(suffix); i++) {
+ for (i = 0; i < nr; i++) {
int suffix_len = strlen(suffix[i]);
if (suffix_len <= len
&& !memcmp(string, suffix[i], suffix_len))
@@ -430,6 +430,18 @@ static inline int upstream_mark(const char *string, int len)
return 0;
}
+static inline int upstream_mark(const char *string, int len)
+{
+ const char *suffix[] = { "@{upstream}", "@{u}" };
+ return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
+static inline int push_mark(const char *string, int len)
+{
+ const char *suffix[] = { "@{push}" };
+ return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
@@ -477,7 +489,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
nth_prior = 1;
continue;
}
- if (!upstream_mark(str + at, len - at)) {
+ if (!upstream_mark(str + at, len - at) &&
+ !push_mark(str + at, len - at)) {
reflog_len = (len-1) - (at+2);
len = at;
}
@@ -832,11 +845,11 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
/* Remember to update object flag allocation in object.h */
#define ONELINE_SEEN (1u<<20)
-static int handle_one_ref(const char *path,
- const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_ref(const char *path, const struct object_id *oid,
+ int flag, void *cb_data)
{
struct commit_list **list = cb_data;
- struct object *object = parse_object(sha1);
+ struct object *object = parse_object(oid->hash);
if (!object)
return 0;
if (object->type == OBJ_TAG) {
@@ -1056,46 +1069,36 @@ static void set_shortened_ref(struct strbuf *buf, const char *ref)
free(s);
}
-static const char *get_upstream_branch(const char *branch_buf, int len)
-{
- char *branch = xstrndup(branch_buf, len);
- struct branch *upstream = branch_get(*branch ? branch : NULL);
-
- /*
- * Upstream can be NULL only if branch refers to HEAD and HEAD
- * points to something different than a branch.
- */
- if (!upstream)
- die(_("HEAD does not point to a branch"));
- if (!upstream->merge || !upstream->merge[0]->dst) {
- if (!ref_exists(upstream->refname))
- die(_("No such branch: '%s'"), branch);
- if (!upstream->merge) {
- die(_("No upstream configured for branch '%s'"),
- upstream->name);
- }
- die(
- _("Upstream branch '%s' not stored as a remote-tracking branch"),
- upstream->merge[0]->src);
- }
- free(branch);
-
- return upstream->merge[0]->dst;
-}
-
-static int interpret_upstream_mark(const char *name, int namelen,
- int at, struct strbuf *buf)
+static int interpret_branch_mark(const char *name, int namelen,
+ int at, struct strbuf *buf,
+ int (*get_mark)(const char *, int),
+ const char *(*get_data)(struct branch *,
+ struct strbuf *))
{
int len;
+ struct branch *branch;
+ struct strbuf err = STRBUF_INIT;
+ const char *value;
- len = upstream_mark(name + at, namelen - at);
+ len = get_mark(name + at, namelen - at);
if (!len)
return -1;
if (memchr(name, ':', at))
return -1;
- set_shortened_ref(buf, get_upstream_branch(name, at));
+ if (at) {
+ char *name_str = xmemdupz(name, at);
+ branch = branch_get(name_str);
+ free(name_str);
+ } else
+ branch = branch_get(NULL);
+
+ value = get_data(branch, &err);
+ if (!value)
+ die("%s", err.buf);
+
+ set_shortened_ref(buf, value);
return len + at;
}
@@ -1146,7 +1149,13 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
if (len > 0)
return reinterpret(name, namelen, len, buf);
- len = interpret_upstream_mark(name, namelen, at - name, buf);
+ len = interpret_branch_mark(name, namelen, at - name, buf,
+ upstream_mark, branch_get_upstream);
+ if (len > 0)
+ return len;
+
+ len = interpret_branch_mark(name, namelen, at - name, buf,
+ push_mark, branch_get_push);
if (len > 0)
return len;
}
@@ -1370,6 +1379,7 @@ static int get_sha1_with_context_1(const char *name,
int pos;
if (!only_to_die && namelen > 2 && name[1] == '/') {
struct commit_list *list = NULL;
+
for_each_ref(handle_one_ref, &list);
commit_list_sort_by_date(&list);
return get_sha1_oneline(name + 2, sha1, list);
@@ -1433,11 +1443,19 @@ static int get_sha1_with_context_1(const char *name,
new_filename = resolve_relative_path(filename);
if (new_filename)
filename = new_filename;
- ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
- if (ret && only_to_die) {
- diagnose_invalid_sha1_path(prefix, filename,
- tree_sha1,
- name, len);
+ if (flags & GET_SHA1_FOLLOW_SYMLINKS) {
+ ret = get_tree_entry_follow_symlinks(tree_sha1,
+ filename, sha1, &oc->symlink_path,
+ &oc->mode);
+ } else {
+ ret = get_tree_entry(tree_sha1, filename,
+ sha1, &oc->mode);
+ if (ret && only_to_die) {
+ diagnose_invalid_sha1_path(prefix,
+ filename,
+ tree_sha1,
+ name, len);
+ }
}
hashcpy(oc->tree, tree_sha1);
strlcpy(oc->path, filename, sizeof(oc->path));
@@ -1468,5 +1486,7 @@ void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)
int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc)
{
+ if (flags & GET_SHA1_FOLLOW_SYMLINKS && flags & GET_SHA1_ONLY_TO_DIE)
+ die("BUG: incompatible flags for get_sha1_with_context");
return get_sha1_with_context_1(str, flags, NULL, sha1, orc);
}