Merge branch 'db/remote-builtin' into jk/send-pack
authorJunio C Hamano <gitster@pobox.com>
Wed, 14 Nov 2007 11:09:52 +0000 (03:09 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Nov 2007 11:09:52 +0000 (03:09 -0800)
* db/remote-builtin:
  Reteach builtin-ls-remote to understand remotes
  Build in ls-remote
  Use built-in send-pack.
  Build-in send-pack, with an API for other programs to call.
  Build-in peek-remote, using transport infrastructure.
  Miscellaneous const changes and utilities

Conflicts:

transport.c

17 files changed:
Makefile
builtin-fetch.c
builtin-ls-remote.c [new file with mode: 0644]
builtin-send-pack.c [moved from send-pack.c with 87% similarity]
builtin.h
cache.h
connect.c
contrib/examples/git-ls-remote.sh [moved from git-ls-remote.sh with 100% similarity]
git.c
http-push.c
peek-remote.c [deleted file]
remote.c
remote.h
send-pack.h [new file with mode: 0644]
t/t5512-ls-remote.sh [new file with mode: 0755]
transport.c
transport.h

index 9c6776e..af827f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -212,7 +212,6 @@ BASIC_LDFLAGS =
 SCRIPT_SH = \
        git-bisect.sh git-checkout.sh \
        git-clean.sh git-clone.sh git-commit.sh \
-       git-ls-remote.sh \
        git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
        git-pull.sh git-rebase.sh git-rebase--interactive.sh \
        git-repack.sh git-request-pull.sh \
@@ -241,7 +240,7 @@ PROGRAMS = \
        git-fast-import$X \
        git-daemon$X \
        git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \
-       git-peek-remote$X git-receive-pack$X \
+       git-receive-pack$X \
        git-send-pack$X git-shell$X \
        git-show-index$X \
        git-unpack-file$X \
@@ -347,6 +346,7 @@ BUILTIN_OBJS = \
        builtin-log.o \
        builtin-ls-files.o \
        builtin-ls-tree.o \
+       builtin-ls-remote.o \
        builtin-mailinfo.o \
        builtin-mailsplit.o \
        builtin-merge-base.o \
@@ -359,6 +359,7 @@ BUILTIN_OBJS = \
        builtin-push.o \
        builtin-read-tree.o \
        builtin-reflog.o \
+       builtin-send-pack.o \
        builtin-config.o \
        builtin-rerere.o \
        builtin-reset.o \
index 5f5b59b..6b1750d 100644 (file)
@@ -29,7 +29,7 @@ static void unlock_pack_on_signal(int signo)
 }
 
 static void add_merge_config(struct ref **head,
-                          struct ref *remote_refs,
+                          const struct ref *remote_refs,
                           struct branch *branch,
                           struct ref ***tail)
 {
@@ -77,7 +77,7 @@ static struct ref *get_ref_map(struct transport *transport,
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
 
-       struct ref *remote_refs = transport_get_remote_refs(transport);
+       const struct ref *remote_refs = transport_get_remote_refs(transport);
 
        if (ref_count || tags) {
                for (i = 0; i < ref_count; i++) {
@@ -354,12 +354,12 @@ static struct ref *find_non_local_tags(struct transport *transport,
        struct path_list new_refs = { NULL, 0, 0, 1 };
        char *ref_name;
        int ref_name_len;
-       unsigned char *ref_sha1;
-       struct ref *tag_ref;
+       const unsigned char *ref_sha1;
+       const struct ref *tag_ref;
        struct ref *rm = NULL;
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
-       struct ref *ref;
+       const struct ref *ref;
 
        for_each_ref(add_existing, &existing_refs);
        for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c
new file mode 100644 (file)
index 0000000..56f3f88
--- /dev/null
@@ -0,0 +1,74 @@
+#include "builtin.h"
+#include "cache.h"
+#include "transport.h"
+#include "remote.h"
+
+static const char ls_remote_usage[] =
+"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+
+int cmd_ls_remote(int argc, const char **argv, const char *prefix)
+{
+       int i;
+       const char *dest = NULL;
+       int nongit = 0;
+       unsigned flags = 0;
+       const char *uploadpack = NULL;
+
+       struct remote *remote;
+       struct transport *transport;
+       const struct ref *ref;
+
+       setup_git_directory_gently(&nongit);
+
+       for (i = 1; i < argc; i++) {
+               const char *arg = argv[i];
+
+               if (*arg == '-') {
+                       if (!prefixcmp(arg, "--upload-pack=")) {
+                               uploadpack = arg + 14;
+                               continue;
+                       }
+                       if (!prefixcmp(arg, "--exec=")) {
+                               uploadpack = arg + 7;
+                               continue;
+                       }
+                       if (!strcmp("--tags", arg)) {
+                               flags |= REF_TAGS;
+                               continue;
+                       }
+                       if (!strcmp("--heads", arg)) {
+                               flags |= REF_HEADS;
+                               continue;
+                       }
+                       if (!strcmp("--refs", arg)) {
+                               flags |= REF_NORMAL;
+                               continue;
+                       }
+                       usage(ls_remote_usage);
+               }
+               dest = arg;
+               break;
+       }
+
+       if (!dest || i != argc - 1)
+               usage(ls_remote_usage);
+
+       remote = nongit ? NULL : remote_get(dest);
+       if (remote && !remote->url_nr)
+               die("remote %s has no configured URL", dest);
+       transport = transport_get(remote, remote ? remote->url[0] : dest);
+       if (uploadpack != NULL)
+               transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
+
+       ref = transport_get_remote_refs(transport);
+
+       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;
+       }
+       return 0;
+}
similarity index 87%
rename from send-pack.c
rename to builtin-send-pack.c
index b74fd45..947c42b 100644 (file)
@@ -5,16 +5,15 @@
 #include "pkt-line.h"
 #include "run-command.h"
 #include "remote.h"
+#include "send-pack.h"
 
 static const char send_pack_usage[] =
 "git-send-pack [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
-static const char *receivepack = "git-receive-pack";
-static int verbose;
-static int send_all;
-static int force_update;
-static int use_thin_pack;
-static int dry_run;
+
+static struct send_pack_args args = {
+       /* .receivepack = */ "git-receive-pack",
+};
 
 /*
  * Make a pack stream and spit it out into file descriptor fd
@@ -26,7 +25,7 @@ static int pack_objects(int fd, struct ref *refs)
         * the revision parameters to it via its stdin and
         * let its stdout go back to the other end.
         */
-       const char *args[] = {
+       const char *argv[] = {
                "pack-objects",
                "--all-progress",
                "--revs",
@@ -36,10 +35,10 @@ static int pack_objects(int fd, struct ref *refs)
        };
        struct child_process po;
 
-       if (use_thin_pack)
-               args[4] = "--thin";
+       if (args.use_thin_pack)
+               argv[4] = "--thin";
        memset(&po, 0, sizeof(po));
-       po.argv = args;
+       po.argv = argv;
        po.in = -1;
        po.out = fd;
        po.git_cmd = 1;
@@ -207,7 +206,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
        }
 }
 
-static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec)
+static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec)
 {
        struct ref *ref;
        int new_refs;
@@ -230,7 +229,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
        if (!remote_tail)
                remote_tail = &remote_refs;
        if (match_refs(local_refs, remote_refs, &remote_tail,
-                      nr_refspec, refspec, send_all))
+                      nr_refspec, refspec, args.send_all))
                return -1;
 
        if (!remote_refs) {
@@ -259,7 +258,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                }
                if (!will_delete_ref &&
                    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
-                       if (verbose)
+                       if (args.verbose)
                                fprintf(stderr, "'%s': up-to-date\n", ref->name);
                        continue;
                }
@@ -283,7 +282,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                 *     always allowed.
                 */
 
-               if (!force_update &&
+               if (!args.force_update &&
                    !will_delete_ref &&
                    !is_null_sha1(ref->old_sha1) &&
                    !ref->force) {
@@ -313,7 +312,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                strcpy(old_hex, sha1_to_hex(ref->old_sha1));
                new_hex = sha1_to_hex(ref->new_sha1);
 
-               if (!dry_run) {
+               if (!args.dry_run) {
                        if (ask_for_status_report) {
                                packet_write(out, "%s %s %s%c%s",
                                        old_hex, new_hex, ref->name, 0,
@@ -338,7 +337,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
        }
 
        packet_flush(out);
-       if (new_refs && !dry_run)
+       if (new_refs && !args.dry_run)
                ret = pack_objects(out, remote_refs);
        close(out);
 
@@ -347,7 +346,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                        ret = -4;
        }
 
-       if (!dry_run && remote && ret == 0) {
+       if (!args.dry_run && remote && ret == 0) {
                for (ref = remote_refs; ref; ref = ref->next)
                        update_tracking_ref(remote, ref);
        }
@@ -357,7 +356,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
        return ret;
 }
 
-static void verify_remote_names(int nr_heads, char **heads)
+static void verify_remote_names(int nr_heads, const char **heads)
 {
        int i;
 
@@ -378,30 +377,25 @@ static void verify_remote_names(int nr_heads, char **heads)
        }
 }
 
-int main(int argc, char **argv)
+int cmd_send_pack(int argc, const char **argv, const char *prefix)
 {
        int i, nr_heads = 0;
-       char *dest = NULL;
-       char **heads = NULL;
-       int fd[2], ret;
-       struct child_process *conn;
-       char *remote_name = NULL;
+       const char **heads = NULL;
+       const char *remote_name = NULL;
        struct remote *remote = NULL;
-
-       setup_git_directory();
-       git_config(git_default_config);
+       const char *dest = NULL;
 
        argv++;
        for (i = 1; i < argc; i++, argv++) {
-               char *arg = *argv;
+               const char *arg = *argv;
 
                if (*arg == '-') {
                        if (!prefixcmp(arg, "--receive-pack=")) {
-                               receivepack = arg + 15;
+                               args.receivepack = arg + 15;
                                continue;
                        }
                        if (!prefixcmp(arg, "--exec=")) {
-                               receivepack = arg + 7;
+                               args.receivepack = arg + 7;
                                continue;
                        }
                        if (!prefixcmp(arg, "--remote=")) {
@@ -409,23 +403,23 @@ int main(int argc, char **argv)
                                continue;
                        }
                        if (!strcmp(arg, "--all")) {
-                               send_all = 1;
+                               args.send_all = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--dry-run")) {
-                               dry_run = 1;
+                               args.dry_run = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--force")) {
-                               force_update = 1;
+                               args.force_update = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--verbose")) {
-                               verbose = 1;
+                               args.verbose = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--thin")) {
-                               use_thin_pack = 1;
+                               args.use_thin_pack = 1;
                                continue;
                        }
                        usage(send_pack_usage);
@@ -434,15 +428,14 @@ int main(int argc, char **argv)
                        dest = arg;
                        continue;
                }
-               heads = argv;
+               heads = (const char **) argv;
                nr_heads = argc - i;
                break;
        }
        if (!dest)
                usage(send_pack_usage);
-       if (heads && send_all)
+       if (heads && args.send_all)
                usage(send_pack_usage);
-       verify_remote_names(nr_heads, heads);
 
        if (remote_name) {
                remote = remote_get(remote_name);
@@ -452,8 +445,22 @@ int main(int argc, char **argv)
                }
        }
 
-       conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0);
-       ret = send_pack(fd[0], fd[1], remote, nr_heads, heads);
+       return send_pack(&args, dest, remote, nr_heads, heads);
+}
+
+int send_pack(struct send_pack_args *my_args,
+             const char *dest, struct remote *remote,
+             int nr_heads, const char **heads)
+{
+       int fd[2], ret;
+       struct child_process *conn;
+
+       memcpy(&args, my_args, sizeof(args));
+
+       verify_remote_names(nr_heads, heads);
+
+       conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
+       ret = do_send_pack(fd[0], fd[1], remote, nr_heads, heads);
        close(fd[0]);
        close(fd[1]);
        ret |= finish_connect(conn);
index 9a6213a..525107f 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -48,6 +48,7 @@ extern int cmd_log(int argc, const char **argv, const char *prefix);
 extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_ls_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
 extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
@@ -69,6 +70,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
 extern int cmd_revert(int argc, const char **argv, const char *prefix);
 extern int cmd_rm(int argc, const char **argv, const char *prefix);
 extern int cmd_runstatus(int argc, const char **argv, const char *prefix);
+extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
 extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
diff --git a/cache.h b/cache.h
index f0a25c7..e5ea637 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -504,7 +504,7 @@ struct ref {
 #define REF_TAGS       (1u << 2)
 
 #define CONNECT_VERBOSE       (1u << 0)
-extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags);
+extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
 extern int finish_connect(struct child_process *conn);
 extern int path_match(const char *path, int nr, char **match);
 extern int get_ack(int fd, unsigned char *result_sha1);
index 44e423d..3aefd4a 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -36,6 +36,11 @@ static int check_ref(const char *name, int len, unsigned int flags)
        return !(flags & ~REF_NORMAL);
 }
 
+int check_ref_type(const struct ref *ref, int flags)
+{
+       return check_ref(ref->name, strlen(ref->name), flags);
+}
+
 /*
  * Read all the refs from the other end
  */
@@ -476,9 +481,10 @@ char *get_port(char *host)
  *
  * If it returns, the connect is successful; it just dies on errors.
  */
-struct child_process *git_connect(int fd[2], char *url,
+struct child_process *git_connect(int fd[2], const char *url_orig,
                                  const char *prog, int flags)
 {
+       char *url = xstrdup(url_orig);
        char *host, *path = url;
        char *end;
        int c;
@@ -568,6 +574,7 @@ struct child_process *git_connect(int fd[2], char *url,
                             prog, path, 0,
                             target_host, 0);
                free(target_host);
+               free(url);
                if (free_path)
                        free(path);
                return NULL;
@@ -619,6 +626,7 @@ struct child_process *git_connect(int fd[2], char *url,
        fd[0] = conn->out; /* read from child's stdout */
        fd[1] = conn->in;  /* write to child's stdin */
        strbuf_release(&cmd);
+       free(url);
        if (free_path)
                free(path);
        return conn;
diff --git a/git.c b/git.c
index 4a250f7..6c5f9af 100644 (file)
--- a/git.c
+++ b/git.c
@@ -321,6 +321,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "log", cmd_log, RUN_SETUP | USE_PAGER },
                { "ls-files", cmd_ls_files, RUN_SETUP },
                { "ls-tree", cmd_ls_tree, RUN_SETUP },
+               { "ls-remote", cmd_ls_remote },
                { "mailinfo", cmd_mailinfo },
                { "mailsplit", cmd_mailsplit },
                { "merge-base", cmd_merge_base, RUN_SETUP },
@@ -328,6 +329,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
                { "name-rev", cmd_name_rev, RUN_SETUP },
                { "pack-objects", cmd_pack_objects, RUN_SETUP },
+               { "peek-remote", cmd_ls_remote },
                { "pickaxe", cmd_blame, RUN_SETUP },
                { "prune", cmd_prune, RUN_SETUP },
                { "prune-packed", cmd_prune_packed, RUN_SETUP },
@@ -342,6 +344,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
                { "rm", cmd_rm, RUN_SETUP },
                { "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },
+               { "send-pack", cmd_send_pack, RUN_SETUP },
                { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
                { "show-branch", cmd_show_branch, RUN_SETUP },
                { "show", cmd_show, RUN_SETUP | USE_PAGER },
index 9314621..99328f5 100644 (file)
@@ -2393,7 +2393,7 @@ int main(int argc, char **argv)
        if (!remote_tail)
                remote_tail = &remote_refs;
        if (match_refs(local_refs, remote_refs, &remote_tail,
-                      nr_refspec, refspec, push_all))
+                      nr_refspec, (const char **) refspec, push_all))
                return -1;
        if (!remote_refs) {
                fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
diff --git a/peek-remote.c b/peek-remote.c
deleted file mode 100644 (file)
index 8d20f7c..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#include "cache.h"
-#include "refs.h"
-#include "pkt-line.h"
-
-static const char peek_remote_usage[] =
-"git-peek-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
-static const char *uploadpack = "git-upload-pack";
-
-static int peek_remote(int fd[2], unsigned flags)
-{
-       struct ref *ref;
-
-       get_remote_heads(fd[0], &ref, 0, NULL, flags);
-       packet_flush(fd[1]);
-
-       while (ref) {
-               printf("%s      %s\n", sha1_to_hex(ref->old_sha1), ref->name);
-               ref = ref->next;
-       }
-       return 0;
-}
-
-int main(int argc, char **argv)
-{
-       int i, ret;
-       char *dest = NULL;
-       int fd[2];
-       struct child_process *conn;
-       int nongit = 0;
-       unsigned flags = 0;
-
-       setup_git_directory_gently(&nongit);
-
-       for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
-
-               if (*arg == '-') {
-                       if (!prefixcmp(arg, "--upload-pack=")) {
-                               uploadpack = arg + 14;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--exec=")) {
-                               uploadpack = arg + 7;
-                               continue;
-                       }
-                       if (!strcmp("--tags", arg)) {
-                               flags |= REF_TAGS;
-                               continue;
-                       }
-                       if (!strcmp("--heads", arg)) {
-                               flags |= REF_HEADS;
-                               continue;
-                       }
-                       if (!strcmp("--refs", arg)) {
-                               flags |= REF_NORMAL;
-                               continue;
-                       }
-                       usage(peek_remote_usage);
-               }
-               dest = arg;
-               break;
-       }
-
-       if (!dest || i != argc - 1)
-               usage(peek_remote_usage);
-
-       conn = git_connect(fd, dest, uploadpack, 0);
-       ret = peek_remote(fd, flags);
-       close(fd[0]);
-       close(fd[1]);
-       ret |= finish_connect(conn);
-       return !!ret;
-}
index bec2ba1..59defdb 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -485,7 +485,7 @@ struct ref *alloc_ref(unsigned namelen)
        return ret;
 }
 
-static struct ref *copy_ref(struct ref *ref)
+static struct ref *copy_ref(const struct ref *ref)
 {
        struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);
        memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1);
@@ -493,6 +493,18 @@ static struct ref *copy_ref(struct ref *ref)
        return ret;
 }
 
+struct ref *copy_ref_list(const struct ref *ref)
+{
+       struct ref *ret = NULL;
+       struct ref **tail = &ret;
+       while (ref) {
+               *tail = copy_ref(ref);
+               ref = ref->next;
+               tail = &((*tail)->next);
+       }
+       return ret;
+}
+
 void free_refs(struct ref *ref)
 {
        struct ref *next;
@@ -710,7 +722,7 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
  * without thinking.
  */
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-              int nr_refspec, char **refspec, int all)
+              int nr_refspec, const char **refspec, int all)
 {
        struct refspec *rs =
                parse_ref_spec(nr_refspec, (const char **) refspec);
@@ -810,10 +822,10 @@ int branch_merge_matches(struct branch *branch,
        return ref_matches_abbrev(branch->merge[i]->src, refname);
 }
 
-static struct ref *get_expanded_map(struct ref *remote_refs,
+static struct ref *get_expanded_map(const struct ref *remote_refs,
                                    const struct refspec *refspec)
 {
-       struct ref *ref;
+       const struct ref *ref;
        struct ref *ret = NULL;
        struct ref **tail = &ret;
 
@@ -824,7 +836,7 @@ static struct ref *get_expanded_map(struct ref *remote_refs,
                if (strchr(ref->name, '^'))
                        continue; /* a dereference item */
                if (!prefixcmp(ref->name, refspec->src)) {
-                       char *match;
+                       const char *match;
                        struct ref *cpy = copy_ref(ref);
                        match = ref->name + remote_prefix_len;
 
@@ -842,9 +854,9 @@ static struct ref *get_expanded_map(struct ref *remote_refs,
        return ret;
 }
 
-static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name)
+static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const char *name)
 {
-       struct ref *ref;
+       const struct ref *ref;
        for (ref = refs; ref; ref = ref->next) {
                if (ref_matches_abbrev(name, ref->name))
                        return ref;
@@ -852,9 +864,9 @@ static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name)
        return NULL;
 }
 
-struct ref *get_remote_ref(struct ref *remote_refs, const char *name)
+struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)
 {
-       struct ref *ref = find_ref_by_name_abbrev(remote_refs, name);
+       const struct ref *ref = find_ref_by_name_abbrev(remote_refs, name);
 
        if (!ref)
                return NULL;
@@ -887,7 +899,7 @@ static struct ref *get_local_ref(const char *name)
        return ret;
 }
 
-int get_fetch_map(struct ref *remote_refs,
+int get_fetch_map(const struct ref *remote_refs,
                  const struct refspec *refspec,
                  struct ref ***tail,
                  int missing_ok)
index 878b4ec..6a4c7a0 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -44,6 +44,10 @@ struct refspec {
 
 struct ref *alloc_ref(unsigned namelen);
 
+struct ref *copy_ref_list(const struct ref *ref);
+
+int check_ref_type(const struct ref *ref, int flags);
+
 /*
  * Frees the entire list and peers of elements.
  */
@@ -57,7 +61,7 @@ void ref_remove_duplicates(struct ref *ref_map);
 struct refspec *parse_ref_spec(int nr_refspec, const char **refspec);
 
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-              int nr_refspec, char **refspec, int all);
+              int nr_refspec, const char **refspec, int all);
 
 /*
  * Given a list of the remote refs and the specification of things to
@@ -71,10 +75,10 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
  * missing_ok is usually false, but when we are adding branch.$name.merge
  * it is Ok if the branch is not at the remote anymore.
  */
-int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec,
+int get_fetch_map(const struct ref *remote_refs, const struct refspec *refspec,
                  struct ref ***tail, int missing_ok);
 
-struct ref *get_remote_ref(struct ref *remote_refs, const char *name);
+struct ref *get_remote_ref(const struct ref *remote_refs, const char *name);
 
 /*
  * For the given remote, reads the refspec's src and sets the other fields.
diff --git a/send-pack.h b/send-pack.h
new file mode 100644 (file)
index 0000000..7a24f71
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef SEND_PACK_H
+#define SEND_PACK_H
+
+struct send_pack_args {
+       const char *receivepack;
+       unsigned verbose:1,
+               send_all:1,
+               force_update:1,
+               use_thin_pack:1,
+               dry_run:1;
+};
+
+int send_pack(struct send_pack_args *args,
+             const char *dest, struct remote *remote,
+             int nr_heads, const char **heads);
+
+#endif
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
new file mode 100755 (executable)
index 0000000..6ec5f7c
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='git ls-remote'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+       >file &&
+       git add file &&
+       test_tick &&
+       git commit -m initial &&
+       git tag mark &&
+       git show-ref --tags -d | sed -e "s/ /   /" >expected.tag &&
+       (
+               echo "$(git rev-parse HEAD)     HEAD"
+               git show-ref -d | sed -e "s/ /  /"
+       ) >expected.all &&
+
+       git remote add self $(pwd)/.git
+
+'
+
+test_expect_success 'ls-remote --tags .git' '
+
+       git ls-remote --tags .git >actual &&
+       diff -u expected.tag actual
+
+'
+
+test_expect_success 'ls-remote .git' '
+
+       git ls-remote .git >actual &&
+       diff -u expected.all actual
+
+'
+
+test_expect_success 'ls-remote --tags self' '
+
+       git ls-remote --tags self >actual &&
+       diff -u expected.tag actual
+
+'
+
+test_expect_success 'ls-remote self' '
+
+       git ls-remote self >actual &&
+       diff -u expected.all actual
+
+'
+
+test_done
index e8a2608..5cb809b 100644 (file)
@@ -6,6 +6,7 @@
 #endif
 #include "pkt-line.h"
 #include "fetch-pack.h"
+#include "send-pack.h"
 #include "walker.h"
 #include "bundle.h"
 #include "dir.h"
@@ -141,7 +142,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
        }
 }
 
-static struct ref *get_refs_via_rsync(const struct transport *transport)
+static struct ref *get_refs_via_rsync(struct transport *transport)
 {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
        struct ref dummy, *tail = &dummy;
@@ -430,7 +431,7 @@ static int missing__target(int code, int result)
 
 #define missing_target(a) missing__target((a)->http_code, (a)->curl_result)
 
-static struct ref *get_refs_via_curl(const struct transport *transport)
+static struct ref *get_refs_via_curl(struct transport *transport)
 {
        struct buffer buffer;
        char *data, *start, *mid;
@@ -527,7 +528,7 @@ struct bundle_transport_data {
        struct bundle_header header;
 };
 
-static struct ref *get_refs_from_bundle(const struct transport *transport)
+static struct ref *get_refs_from_bundle(struct transport *transport)
 {
        struct bundle_transport_data *data = transport->data;
        struct ref *result = NULL;
@@ -599,7 +600,7 @@ static int set_git_option(struct transport *connection,
        return 1;
 }
 
-static struct ref *get_refs_via_connect(const struct transport *transport)
+static struct ref *get_refs_via_connect(struct transport *transport)
 {
        struct git_transport_data *data = transport->data;
        struct ref *refs;
@@ -652,50 +653,16 @@ static int fetch_refs_via_pack(struct transport *transport,
 static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
 {
        struct git_transport_data *data = transport->data;
-       const char **argv;
-       char *rem;
-       int argc;
-       int err;
+       struct send_pack_args args;
 
-       argv = xmalloc((refspec_nr + 12) * sizeof(char *));
-       argv[0] = "send-pack";
-       argc = 1;
-       if (flags & TRANSPORT_PUSH_ALL)
-               argv[argc++] = "--all";
-       if (flags & TRANSPORT_PUSH_FORCE)
-               argv[argc++] = "--force";
-       if (flags & TRANSPORT_PUSH_DRY_RUN)
-               argv[argc++] = "--dry-run";
-       if (flags & TRANSPORT_PUSH_VERBOSE)
-               argv[argc++] = "--verbose";
-       if (data->receivepack) {
-               char *rp = xmalloc(strlen(data->receivepack) + 16);
-               sprintf(rp, "--receive-pack=%s", data->receivepack);
-               argv[argc++] = rp;
-       }
-       if (data->thin)
-               argv[argc++] = "--thin";
-       rem = xmalloc(strlen(transport->remote->name) + 10);
-       sprintf(rem, "--remote=%s", transport->remote->name);
-       argv[argc++] = rem;
-       argv[argc++] = transport->url;
-       while (refspec_nr--)
-               argv[argc++] = *refspec++;
-       argv[argc] = NULL;
-       err = run_command_v_opt(argv, RUN_GIT_CMD);
-       switch (err) {
-       case -ERR_RUN_COMMAND_FORK:
-               error("unable to fork for %s", argv[0]);
-       case -ERR_RUN_COMMAND_EXEC:
-               error("unable to exec %s", argv[0]);
-               break;
-       case -ERR_RUN_COMMAND_WAITPID:
-       case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
-       case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-       case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-               error("%s died with strange error", argv[0]);
-       }
-       return !!err;
+       args.receivepack = data->receivepack;
+       args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
+       args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
+       args.use_thin_pack = data->thin;
+       args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
+       args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
+
+       return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);
 }
 
 static int disconnect_git(struct transport *transport)
@@ -787,7 +754,7 @@ int transport_push(struct transport *transport,
        return transport->push(transport, refspec_nr, refspec, flags);
 }
 
-struct ref *transport_get_remote_refs(struct transport *transport)
+const struct ref *transport_get_remote_refs(struct transport *transport)
 {
        if (!transport->remote_refs)
                transport->remote_refs = transport->get_refs_list(transport);
index 2f80ab4..a2a36d0 100644 (file)
@@ -8,7 +8,7 @@ struct transport {
        struct remote *remote;
        const char *url;
        void *data;
-       struct ref *remote_refs;
+       const struct ref *remote_refs;
 
        /**
         * Returns 0 if successful, positive if the option is not
@@ -18,7 +18,7 @@ struct transport {
        int (*set_option)(struct transport *connection, const char *name,
                          const char *value);
 
-       struct ref *(*get_refs_list)(const struct transport *transport);
+       struct ref *(*get_refs_list)(struct transport *transport);
        int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs);
        int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
 
@@ -62,7 +62,7 @@ int transport_set_option(struct transport *transport, const char *name,
 int transport_push(struct transport *connection,
                   int refspec_nr, const char **refspec, int flags);
 
-struct ref *transport_get_remote_refs(struct transport *transport);
+const struct ref *transport_get_remote_refs(struct transport *transport);
 
 int transport_fetch_refs(struct transport *transport, struct ref *refs);
 void transport_unlock_pack(struct transport *transport);