builtin-ls-remote.con commit Merge branch 'jc/spht' (4eb39e9)
   1#include "builtin.h"
   2#include "cache.h"
   3#include "transport.h"
   4#include "remote.h"
   5
   6static const char ls_remote_usage[] =
   7"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
   8
   9/*
  10 * pattern is a list of tail-part of accepted refnames.  Is there one
  11 * among them that is a suffix of the path?  Directory boundary must
  12 * be honored when checking this match.  IOW, patterns "master" and
  13 * "sa/master" both match path "refs/hold/sa/master".  On the other
  14 * hand, path "refs/hold/foosa/master" is matched by "master" but not
  15 * by "sa/master".
  16 */
  17
  18static int tail_match(const char **pattern, const char *path)
  19{
  20        int pathlen;
  21        const char *p;
  22
  23        if (!*pattern)
  24                return 1; /* no restriction */
  25
  26        for (pathlen = strlen(path); (p = *pattern); pattern++) {
  27                int pfxlen = pathlen - strlen(p);
  28                if (pfxlen < 0)
  29                        continue; /* pattern is longer, will never match */
  30                if (strcmp(path + pfxlen, p))
  31                        continue; /* no tail match */
  32                if (!pfxlen || path[pfxlen - 1] == '/')
  33                        return 1; /* fully match at directory boundary */
  34        }
  35        return 0;
  36}
  37
  38int cmd_ls_remote(int argc, const char **argv, const char *prefix)
  39{
  40        int i;
  41        const char *dest = NULL;
  42        int nongit = 0;
  43        unsigned flags = 0;
  44        const char *uploadpack = NULL;
  45        const char **pattern = NULL;
  46
  47        struct remote *remote;
  48        struct transport *transport;
  49        const struct ref *ref;
  50
  51        setup_git_directory_gently(&nongit);
  52
  53        for (i = 1; i < argc; i++) {
  54                const char *arg = argv[i];
  55
  56                if (*arg == '-') {
  57                        if (!prefixcmp(arg, "--upload-pack=")) {
  58                                uploadpack = arg + 14;
  59                                continue;
  60                        }
  61                        if (!prefixcmp(arg, "--exec=")) {
  62                                uploadpack = arg + 7;
  63                                continue;
  64                        }
  65                        if (!strcmp("--tags", arg)) {
  66                                flags |= REF_TAGS;
  67                                continue;
  68                        }
  69                        if (!strcmp("--heads", arg)) {
  70                                flags |= REF_HEADS;
  71                                continue;
  72                        }
  73                        if (!strcmp("--refs", arg)) {
  74                                flags |= REF_NORMAL;
  75                                continue;
  76                        }
  77                        usage(ls_remote_usage);
  78                }
  79                dest = arg;
  80                break;
  81        }
  82
  83        if (!dest)
  84                usage(ls_remote_usage);
  85        pattern = argv + i + 1;
  86        remote = nongit ? NULL : remote_get(dest);
  87        if (remote && !remote->url_nr)
  88                die("remote %s has no configured URL", dest);
  89        transport = transport_get(remote, remote ? remote->url[0] : dest);
  90        if (uploadpack != NULL)
  91                transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
  92
  93        ref = transport_get_remote_refs(transport);
  94
  95        if (!ref)
  96                return 1;
  97
  98        for ( ; ref; ref = ref->next) {
  99                if (!check_ref_type(ref, flags))
 100                        continue;
 101                if (!tail_match(pattern, ref->name))
 102                        continue;
 103                printf("%s      %s\n", sha1_to_hex(ref->old_sha1), ref->name);
 104        }
 105        return 0;
 106}