Skip to content

Commit 62faad5

Browse files
peffgitster
authored andcommitted
handle_revision_arg: add handle_dotdot() helper
The handle_revision_arg function is rather long, and a big chunk of it is handling the range operators. Let's pull that out to a separate helper. While we're doing so, we can clean up a few of the rough edges that made the flow hard to follow: - instead of manually restoring *dotdot (that we overwrote with a NUL), do the real work in a sub-helper, which makes it clear that the munge/restore lines are a matched pair - eliminate a goto which wasn't actually used for control flow, but only to avoid duplicating a few lines (instead, those lines are pushed into another helper function) - use early returns instead of deep nesting - consistently name all variables for the left-hand side of the range as "a" (rather than "this" or "from") and the right-hand side as "b" (rather than "next", or using the unadorned "sha1" or "flags" from the main function). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent d89797f commit 62faad5

1 file changed

Lines changed: 102 additions & 75 deletions

File tree

revision.c

Lines changed: 102 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,10 +1429,109 @@ static void prepare_show_merge(struct rev_info *revs)
14291429
revs->limited = 1;
14301430
}
14311431

1432+
static int dotdot_missing(const char *arg, char *dotdot,
1433+
struct rev_info *revs, int symmetric)
1434+
{
1435+
if (revs->ignore_missing)
1436+
return 0;
1437+
/* de-munge so we report the full argument */
1438+
*dotdot = '.';
1439+
die(symmetric
1440+
? "Invalid symmetric difference expression %s"
1441+
: "Invalid revision range %s", arg);
1442+
}
1443+
1444+
static int handle_dotdot_1(const char *arg, char *dotdot,
1445+
struct rev_info *revs, int flags,
1446+
int cant_be_filename)
1447+
{
1448+
const char *a_name, *b_name;
1449+
struct object_id a_oid, b_oid;
1450+
struct object *a_obj, *b_obj;
1451+
unsigned int a_flags, b_flags;
1452+
int symmetric = 0;
1453+
unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
1454+
1455+
a_name = arg;
1456+
if (!*a_name)
1457+
a_name = "HEAD";
1458+
1459+
b_name = dotdot + 2;
1460+
if (*b_name == '.') {
1461+
symmetric = 1;
1462+
b_name++;
1463+
}
1464+
if (!*b_name)
1465+
b_name = "HEAD";
1466+
1467+
if (get_sha1_committish(a_name, a_oid.hash) ||
1468+
get_sha1_committish(b_name, b_oid.hash))
1469+
return -1;
1470+
1471+
if (!cant_be_filename) {
1472+
*dotdot = '.';
1473+
verify_non_filename(revs->prefix, arg);
1474+
*dotdot = '\0';
1475+
}
1476+
1477+
a_obj = parse_object(a_oid.hash);
1478+
b_obj = parse_object(b_oid.hash);
1479+
if (!a_obj || !b_obj)
1480+
return dotdot_missing(arg, dotdot, revs, symmetric);
1481+
1482+
if (!symmetric) {
1483+
/* just A..B */
1484+
b_flags = flags;
1485+
a_flags = flags_exclude;
1486+
} else {
1487+
/* A...B -- find merge bases between the two */
1488+
struct commit *a, *b;
1489+
struct commit_list *exclude;
1490+
1491+
a = lookup_commit_reference(a_obj->oid.hash);
1492+
b = lookup_commit_reference(b_obj->oid.hash);
1493+
if (!a || !b)
1494+
return dotdot_missing(arg, dotdot, revs, symmetric);
1495+
1496+
exclude = get_merge_bases(a, b);
1497+
add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
1498+
flags_exclude);
1499+
add_pending_commit_list(revs, exclude, flags_exclude);
1500+
free_commit_list(exclude);
1501+
1502+
b_flags = flags;
1503+
a_flags = flags | SYMMETRIC_LEFT;
1504+
}
1505+
1506+
a_obj->flags |= a_flags;
1507+
b_obj->flags |= b_flags;
1508+
add_rev_cmdline(revs, a_obj, a_name, REV_CMD_LEFT, a_flags);
1509+
add_rev_cmdline(revs, b_obj, b_name, REV_CMD_RIGHT, b_flags);
1510+
add_pending_object(revs, a_obj, a_name);
1511+
add_pending_object(revs, b_obj, b_name);
1512+
return 0;
1513+
}
1514+
1515+
static int handle_dotdot(const char *arg,
1516+
struct rev_info *revs, int flags,
1517+
int cant_be_filename)
1518+
{
1519+
char *dotdot = strstr(arg, "..");
1520+
int ret;
1521+
1522+
if (!dotdot)
1523+
return -1;
1524+
1525+
*dotdot = '\0';
1526+
ret = handle_dotdot_1(arg, dotdot, revs, flags, cant_be_filename);
1527+
*dotdot = '.';
1528+
1529+
return ret;
1530+
}
1531+
14321532
int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt)
14331533
{
14341534
struct object_context oc;
1435-
char *dotdot;
14361535
char *mark;
14371536
struct object *object;
14381537
unsigned char sha1[20];
@@ -1451,80 +1550,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
14511550
return -1;
14521551
}
14531552

1454-
dotdot = strstr(arg, "..");
1455-
if (dotdot) {
1456-
unsigned char from_sha1[20];
1457-
const char *next = dotdot + 2;
1458-
const char *this = arg;
1459-
int symmetric = *next == '.';
1460-
unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
1461-
unsigned int a_flags;
1462-
1463-
*dotdot = 0;
1464-
next += symmetric;
1465-
1466-
if (!*next)
1467-
next = "HEAD";
1468-
if (dotdot == arg)
1469-
this = "HEAD";
1470-
if (!get_sha1_committish(this, from_sha1) &&
1471-
!get_sha1_committish(next, sha1)) {
1472-
struct object *a_obj, *b_obj;
1473-
1474-
if (!cant_be_filename) {
1475-
*dotdot = '.';
1476-
verify_non_filename(revs->prefix, arg);
1477-
*dotdot = '\0';
1478-
}
1479-
1480-
a_obj = parse_object(from_sha1);
1481-
b_obj = parse_object(sha1);
1482-
if (!a_obj || !b_obj) {
1483-
missing:
1484-
*dotdot = '.';
1485-
if (revs->ignore_missing)
1486-
return 0;
1487-
die(symmetric
1488-
? "Invalid symmetric difference expression %s"
1489-
: "Invalid revision range %s", arg);
1490-
}
1491-
1492-
if (!symmetric) {
1493-
/* just A..B */
1494-
a_flags = flags_exclude;
1495-
} else {
1496-
/* A...B -- find merge bases between the two */
1497-
struct commit *a, *b;
1498-
struct commit_list *exclude;
1499-
1500-
a = lookup_commit_reference(a_obj->oid.hash);
1501-
b = lookup_commit_reference(b_obj->oid.hash);
1502-
if (!a || !b)
1503-
goto missing;
1504-
exclude = get_merge_bases(a, b);
1505-
add_rev_cmdline_list(revs, exclude,
1506-
REV_CMD_MERGE_BASE,
1507-
flags_exclude);
1508-
add_pending_commit_list(revs, exclude,
1509-
flags_exclude);
1510-
free_commit_list(exclude);
1511-
1512-
a_flags = flags | SYMMETRIC_LEFT;
1513-
}
1514-
1515-
a_obj->flags |= a_flags;
1516-
b_obj->flags |= flags;
1517-
add_rev_cmdline(revs, a_obj, this,
1518-
REV_CMD_LEFT, a_flags);
1519-
add_rev_cmdline(revs, b_obj, next,
1520-
REV_CMD_RIGHT, flags);
1521-
add_pending_object(revs, a_obj, this);
1522-
add_pending_object(revs, b_obj, next);
1523-
*dotdot = '.';
1524-
return 0;
1525-
}
1526-
*dotdot = '.';
1527-
}
1553+
if (!handle_dotdot(arg, revs, flags, revarg_opt))
1554+
return 0;
15281555

15291556
mark = strstr(arg, "^@");
15301557
if (mark && !mark[2]) {

0 commit comments

Comments
 (0)