{"thread":{"id":"43785","subject":"[PATCH/RFC] Add support for push globbed refspecs","startedAt":"2006-12-11T21:33:41Z","lastAt":"2006-12-11T21:33:41Z","messageCount":1,"participants":["Andy Parkins"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"298773","messageId":"200612112133.42060.andyparkins@gmail.com","threadId":"43785","inReplyTo":null,"subject":"[PATCH/RFC] Add support for push globbed refspecs","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2006-12-11T21:33:41Z","receivedAt":"2006-12-11T21:33:41Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"Just as we now have glob support in fetch refspecs, this patch adds\nsupport for globs in the push refspecs.  In other words you can do:\n\n[remote \"globs\"]\n\turl = proto://host/repo.git\n\tpush = refs/heads/*:refs/remotes/from_me/*\n\nWith this, a git-push will then do a normal directory glob on the local\nref path; whatever it finds will have the matching part extracted and\ninserted into the remote half of the refspec.\n\nNote the following:\n - subdirectories aren't supported\n - globs with more than one \"*\" will probably go /very/ wrong\n\nSigned-off-by: Andy Parkins <andyparkins@gmail.com>\n---\nI'm not sure this is the right way to have done this.\n\nMy feeling is that perhaps a for_each_ref() call and some string\nmanipulation would have been better.  What'd you all reckon?\n\n\n builtin-push.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 70 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-push.c b/builtin-push.c\nindex d23974e..e60db71 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -5,6 +5,7 @@\n #include \"refs.h\"\n #include \"run-command.h\"\n #include \"builtin.h\"\n+#include <glob.h>\n \n #define MAX_URI (16)\n \n@@ -22,6 +23,75 @@ static int refspec_nr;\n static void add_refspec(const char *ref)\n {\n \tint nr = refspec_nr + 1;\n+\tchar *globpos_local = NULL,\n+\t\t *globpos_remote = NULL,\n+\t\t *separator = NULL;\n+\tchar *buffer;\n+\n+\t/* See if the ref is a globref */\n+\tbuffer = xmalloc(strlen(ref)+1);\n+\tstrcpy(buffer, ref);\n+\tseparator = strstr(buffer, \":\");\n+\tif (separator != NULL)\n+\t\tglobpos_remote = strstr(separator, \"*\");\n+\tglobpos_local = strstr(buffer, \"*\");\n+\n+\t/* If globpos is set, then we have enough information to perform\n+\t * the expansion */\n+\tif( globpos_remote != NULL && globpos_local != NULL) {\n+\t\tglob_t globres;\n+\t\tint ret;\n+\t\tunsigned int i;\n+\t\tunsigned int gitpathlen;\n+\t\tchar *newrefspec;\n+\n+\t\t/* Break the refspec into chunks:\n+\t\t *  <localref>:<remote_prefix>*<remoteref_suffix>\n+\t\t */\n+\t\t*separator = '\\0';\n+\t\tseparator++;\n+\t\t*globpos_remote = '\\0';\n+\t\tglobpos_remote++;\n+\t\t/* Now buffer points at localref; separator points at\n+\t\t * remoteref prefix, globpos_remote points at remoteref suffix */\n+\n+\t\t/* Fetch all the matching local refs */\n+\t\tglobres.gl_offs = 0;\n+\t\tret = glob(git_path(\"%s\", buffer), GLOB_ERR, NULL, &globres);\n+\t\tgitpathlen = strlen( git_path(\"\") );\n+\n+\t\tif (ret == 0) {\n+\t\t\tfor (i = 0; i < globres.gl_pathc; i++) {\n+\t\t\t\tchar *p, *q;\n+\n+\t\t\t\tp = globres.gl_pathv[i] + gitpathlen + (globpos_local - buffer);\n+\t\t\t\tq = p + strlen(p) - strlen(globpos_local+1);\n+\n+\t\t\t\tnewrefspec = xmalloc(\n+\t\t\t\t\t\tstrlen(globres.gl_pathv[i] + gitpathlen)\n+\t\t\t\t\t\t+ strlen(separator)\n+\t\t\t\t\t\t+ (q-p)\n+\t\t\t\t\t\t+ strlen( globpos_remote)\n+\t\t\t\t\t\t+ 1 + 1 );\n+\n+\t\t\t\tsprintf( newrefspec, \"%s:%s%.*s%s\",\n+\t\t\t\t\t\tglobres.gl_pathv[i] + gitpathlen,\n+\t\t\t\t\t\tseparator,\n+\t\t\t\t\t\tq-p, p,\n+\t\t\t\t\t\tglobpos_remote );\n+\n+\t\t\t\tadd_refspec( newrefspec );\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* tidy up */\n+\t\tglobfree( &globres );\n+\n+\t\t/* Don't add the globspec */\n+\t\treturn;\n+\t}\n+\tfree(buffer);\n+\n \trefspec = xrealloc(refspec, nr * sizeof(char *));\n \trefspec[nr-1] = ref;\n \trefspec_nr = nr;\n-- \n1.4.4.1.GIT\n"}]}