Re: [PATCH] Restore ls-remote reference pattern matching

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Daniel Barkalow <barkalow@xxxxxxxxxxxx> writes:

> I'd found the same code ("git log -p -- git-ls-remote.sh" also reveals it, 
> and I couldn't remember it's contrib/examples that things end up in), but 
> I don't really follow that shell syntax.

Sorry, I should have been more explicit.

At this point in the scripted version:

	for pat
	do
		case "/$path" in
		*/$pat )
			match=yes
			break ;;
		esac
	done

 - $path is what we read from peek-remote (or the equivalent from curl
   for http), e.g. "refs/heads/master", or "HEAD".

 - we iterate over remainder of arguments to the script, assigning each
   to $pat;

 - we check if the pattern "*/$pat" matches "/$path".  "case" matching
   rule is an entire string match with globbing, so it is asking if
   /$path ends with /$pat.  IOW, $pat="master" matches:

	$path=refs/heads/master
        $path=refs/remotes/origin/master

   but it does not match $path="refs/heads/omaster".

---

 builtin-ls-remote.c |   44 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c
index 56f3f88..bae7c48 100644
--- a/builtin-ls-remote.c
+++ b/builtin-ls-remote.c
@@ -6,6 +6,35 @@
 static const char ls_remote_usage[] =
 "git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
 
+/*
+ * pattern is a list of tail-part of accepted refnames.  Is there one
+ * among then that is a suffix of the path?  Directory boundary must
+ * be honored when doing this match.  IOW, patterns "master" and
+ * "sa/master" both match path "refs/hold/sa/master".  On the other
+ * hand, path "refs/hold/foosa/master" is matched by "master" but not
+ * by "sa/master".
+ */
+
+static int tail_match(const char **pattern, const char *path)
+{
+	int pathlen;
+	const char *p;
+
+	if (!*pattern)
+		return 1; /* no restriction */
+
+	for (pathlen = strlen(path); (p = *pattern); pattern++) {
+		int pfxlen = pathlen - strlen(p);
+		if (pfxlen < 0)
+			continue; /* pattern is longer, will never match */
+		if (strcmp(path + pfxlen, p))
+			continue; /* no tail match */
+		if (!pfxlen || path[pfxlen - 1] == '/')
+			return 1; /* fully match at directory boundary */
+	}
+	return 0;
+}
+
 int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 {
 	int i;
@@ -13,6 +42,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 	int nongit = 0;
 	unsigned flags = 0;
 	const char *uploadpack = NULL;
+	const char **pattern = NULL;
 
 	struct remote *remote;
 	struct transport *transport;
@@ -50,9 +80,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 		break;
 	}
 
-	if (!dest || i != argc - 1)
+	if (!dest)
 		usage(ls_remote_usage);
-
+	pattern = argv + i + 1;
 	remote = nongit ? NULL : remote_get(dest);
 	if (remote && !remote->url_nr)
 		die("remote %s has no configured URL", dest);
@@ -65,10 +95,12 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 	if (!ref)
 		return 1;
 
-	while (ref) {
-		if (check_ref_type(ref, flags))
-			printf("%s	%s\n", sha1_to_hex(ref->old_sha1), ref->name);
-		ref = ref->next;
+	for ( ; ref; ref = ref->next) {
+		if (!check_ref_type(ref, flags))
+			continue;
+		if (!tail_match(pattern, ref->name))
+			continue;
+		printf("%s	%s\n", sha1_to_hex(ref->old_sha1), ref->name);
 	}
 	return 0;
 }
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux