Just as we now have glob support in fetch refspecs, this patch adds support for globs in the push refspecs. In other words you can do: [remote "globs"] url = proto://host/repo.git push = refs/heads/*:refs/remotes/from_me/* With this, a git-push will then do a normal directory glob on the local ref path; whatever it finds will have the matching part extracted and inserted into the remote half of the refspec. Note the following: - subdirectories aren't supported - globs with more than one "*" will probably go /very/ wrong Signed-off-by: Andy Parkins <andyparkins@xxxxxxxxx> --- I'm not sure this is the right way to have done this. My feeling is that perhaps a for_each_ref() call and some string manipulation would have been better. What'd you all reckon? builtin-push.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/builtin-push.c b/builtin-push.c index d23974e..e60db71 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -5,6 +5,7 @@ #include "refs.h" #include "run-command.h" #include "builtin.h" +#include <glob.h> #define MAX_URI (16) @@ -22,6 +23,75 @@ static int refspec_nr; static void add_refspec(const char *ref) { int nr = refspec_nr + 1; + char *globpos_local = NULL, + *globpos_remote = NULL, + *separator = NULL; + char *buffer; + + /* See if the ref is a globref */ + buffer = xmalloc(strlen(ref)+1); + strcpy(buffer, ref); + separator = strstr(buffer, ":"); + if (separator != NULL) + globpos_remote = strstr(separator, "*"); + globpos_local = strstr(buffer, "*"); + + /* If globpos is set, then we have enough information to perform + * the expansion */ + if( globpos_remote != NULL && globpos_local != NULL) { + glob_t globres; + int ret; + unsigned int i; + unsigned int gitpathlen; + char *newrefspec; + + /* Break the refspec into chunks: + * <localref>:<remote_prefix>*<remoteref_suffix> + */ + *separator = '\0'; + separator++; + *globpos_remote = '\0'; + globpos_remote++; + /* Now buffer points at localref; separator points at + * remoteref prefix, globpos_remote points at remoteref suffix */ + + /* Fetch all the matching local refs */ + globres.gl_offs = 0; + ret = glob(git_path("%s", buffer), GLOB_ERR, NULL, &globres); + gitpathlen = strlen( git_path("") ); + + if (ret == 0) { + for (i = 0; i < globres.gl_pathc; i++) { + char *p, *q; + + p = globres.gl_pathv[i] + gitpathlen + (globpos_local - buffer); + q = p + strlen(p) - strlen(globpos_local+1); + + newrefspec = xmalloc( + strlen(globres.gl_pathv[i] + gitpathlen) + + strlen(separator) + + (q-p) + + strlen( globpos_remote) + + 1 + 1 ); + + sprintf( newrefspec, "%s:%s%.*s%s", + globres.gl_pathv[i] + gitpathlen, + separator, + q-p, p, + globpos_remote ); + + add_refspec( newrefspec ); + } + } + + /* tidy up */ + globfree( &globres ); + + /* Don't add the globspec */ + return; + } + free(buffer); + refspec = xrealloc(refspec, nr * sizeof(char *)); refspec[nr-1] = ref; refspec_nr = nr; -- 1.4.4.1.GIT - 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