ref-filter: add an 'rstrip=<N>' option to atoms which deal with refnames

Complimenting the existing 'lstrip=<N>' option, add an 'rstrip=<N>'
option which strips `<N>` slash-separated path components from the end
of the refname (e.g., `%(refname:rstrip=2)` turns `refs/tags/foo` into
`refs`).

Signed-off-by: Karthik Nayak <Karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Karthik Nayak
2017-01-10 14:19:49 +05:30
committed by Junio C Hamano
parent 1a0ca5e358
commit 1a34728e6b
3 changed files with 81 additions and 21 deletions

View File

@ -33,8 +33,8 @@ struct if_then_else {
};
struct refname_atom {
enum { R_NORMAL, R_SHORT, R_LSTRIP } option;
int lstrip;
enum { R_NORMAL, R_SHORT, R_LSTRIP, R_RSTRIP } option;
int lstrip, rstrip;
};
/*
@ -95,6 +95,10 @@ static void refname_atom_parser_internal(struct refname_atom *atom,
atom->option = R_LSTRIP;
if (strtol_i(arg, 10, &atom->lstrip))
die(_("Integer value expected refname:lstrip=%s"), arg);
} else if (skip_prefix(arg, "rstrip=", &arg)) {
atom->option = R_RSTRIP;
if (strtol_i(arg, 10, &atom->rstrip))
die(_("Integer value expected refname:rstrip=%s"), arg);
} else
die(_("unrecognized %%(%s) argument: %s"), name, arg);
}
@ -1125,12 +1129,45 @@ static const char *lstrip_ref_components(const char *refname, int len)
return start;
}
static const char *rstrip_ref_components(const char *refname, int len)
{
long remaining = len;
char *start = xstrdup(refname);
if (len < 0) {
int i;
const char *p = refname;
/* Find total no of '/' separated path-components */
for (i = 0; p[i]; p[i] == '/' ? i++ : *p++)
;
/*
* The number of components we need to strip is now
* the total minus the components to be left (Plus one
* because we count the number of '/', but the number
* of components is one more than the no of '/').
*/
remaining = i + len + 1;
}
while (remaining-- > 0) {
char *p = strrchr(start, '/');
if (p == NULL)
return "";
else
p[0] = '\0';
}
return start;
}
static const char *show_ref(struct refname_atom *atom, const char *refname)
{
if (atom->option == R_SHORT)
return shorten_unambiguous_ref(refname, warn_ambiguous_refs);
else if (atom->option == R_LSTRIP)
return lstrip_ref_components(refname, atom->lstrip);
else if (atom->option == R_RSTRIP)
return rstrip_ref_components(refname, atom->rstrip);
else
return refname;
}