239
return slash;
240
}
241
242
-static inline int tracked_suffix(const char *string, int len)
243
-{
244
- const char *suffix[] = { "@{upstream}", "@{u}" };
245
- int i;
246
-
247
- for (i = 0; i < ARRAY_SIZE(suffix); i++) {
248
- int suffix_len = strlen(suffix[i]);
249
- if (len >= suffix_len && !memcmp(string + len - suffix_len,
250
- suffix[i], suffix_len))
251
- return suffix_len;
252
- }
253
- return 0;
254
-}
255
-
242
/*
243
* *string and *len will only be substituted, and *string returned (for
258
- * later free()ing) if the string passed in is of the form @{-<n>} or
259
- * of the form <branch>@{upstream}.
244
+ * later free()ing) if the string passed in is a magic short-hand form
245
+ * to name a branch.
246
*/
247
static char *substitute_branch_name(const char **string, int *len)
248
{
256
return (char *)*string;
257
}
258
273
- ret = tracked_suffix(*string, *len);
274
- if (ret) {
275
- char *ref = xstrndup(*string, *len - ret);
276
- struct branch *tracking = branch_get(*ref ? ref : NULL);
277
-
278
- if (!tracking)
279
- die ("No tracking branch found for '%s'", ref);
280
- free(ref);
281
- if (tracking->merge && tracking->merge[0]->dst) {
282
- *string = xstrdup(tracking->merge[0]->dst);
283
- *len = strlen(*string);
284
- return (char *)*string;
285
- }
286
- }
287
-
259
return NULL;
260
}
261
325
return logs_found;
326
}
327
328
+static inline int upstream_mark(const char *string, int len)
329
+{
330
+ const char *suffix[] = { "@{upstream}", "@{u}" };
331
+ int i;
332
+
333
+ for (i = 0; i < ARRAY_SIZE(suffix); i++) {
334
+ int suffix_len = strlen(suffix[i]);
335
+ if (suffix_len <= len
336
+ && !memcmp(string, suffix[i], suffix_len))
337
+ return suffix_len;
338
+ }
339
+ return 0;
340
+}
341
+
342
static int get_sha1_1(const char *name, int len, unsigned char *sha1);
343
344
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
356
if (len && str[len-1] == '}') {
357
for (at = len-2; at >= 0; at--) {
358
if (str[at] == '@' && str[at+1] == '{') {
374
- if (!tracked_suffix(str + at, len - at)) {
359
+ if (!upstream_mark(str + at, len - at)) {
360
reflog_len = (len-1) - (at+2);
361
len = at;
362
}
758
}
759
760
/*
776
- * This reads "@{-N}" syntax, finds the name of the Nth previous
777
- * branch we were on, and places the name of the branch in the given
778
- * buf and returns the number of characters parsed if successful.
779
- *
780
- * If the input is not of the accepted format, it returns a negative
781
- * number to signal an error.
782
- *
783
- * If the input was ok but there are not N branch switches in the
784
- * reflog, it returns 0.
761
+ * Parse @{-N} syntax, return the number of characters parsed
762
+ * if successful; otherwise signal an error with negative value.
763
*/
786
-int interpret_branch_name(const char *name, struct strbuf *buf)
764
+static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf)
765
{
766
long nth;
767
int i, retval;
805
return retval;
806
}
807
808
+/*
809
+ * This reads short-hand syntax that not only evaluates to a commit
810
+ * object name, but also can act as if the end user spelled the name
811
+ * of the branch from the command line.
812
+ *
813
+ * - "@{-N}" finds the name of the Nth previous branch we were on, and
814
+ * places the name of the branch in the given buf and returns the
815
+ * number of characters parsed if successful.
816
+ *
817
+ * - "<branch>@{upstream}" finds the name of the other ref that
818
+ * <branch> is configured to merge with (missing <branch> defaults
819
+ * to the current branch), and places the name of the branch in the
820
+ * given buf and returns the number of characters parsed if
821
+ * successful.
822
+ *
823
+ * If the input is not of the accepted format, it returns a negative
824
+ * number to signal an error.
825
+ *
826
+ * If the input was ok but there are not N branch switches in the
827
+ * reflog, it returns 0.
828
+ */
829
+int interpret_branch_name(const char *name, struct strbuf *buf)
830
+{
831
+ char *cp;
832
+ struct branch *upstream;
833
+ int namelen = strlen(name);
834
+ int len = interpret_nth_prior_checkout(name, buf);
835
+ int tmp_len;
836
+
837
+ if (!len)
838
+ return len; /* syntax Ok, not enough switches */
839
+ if (0 < len)
840
+ return len; /* consumed from the front */
841
+ cp = strchr(name, '@');
842
+ if (!cp)
843
+ return -1;
844
+ tmp_len = upstream_mark(cp, namelen - (cp - name));
845
+ if (!tmp_len)
846
+ return -1;
847
+ len = cp + tmp_len - name;
848
+ cp = xstrndup(name, cp - name);
849
+ upstream = branch_get(*cp ? cp : NULL);
850
+ if (!upstream
851
+ || !upstream->merge
852
+ || !upstream->merge[0]->dst)
853
+ return error("No upstream branch found for '%s'", cp);
854
+ free(cp);
855
+ cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
856
+ strbuf_reset(buf);
857
+ strbuf_addstr(buf, cp);
858
+ free(cp);
859
+ return len;
860
+}
861
+
862
/*
863
* This is like "get_sha1_basic()", except it allows "sha1 expressions",
864
* notably "xyz^" for "parent of xyz"