Merge branch 'bw/push-dry-run'
authorJunio C Hamano <gitster@pobox.com>
Fri, 16 Dec 2016 23:27:48 +0000 (15:27 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 16 Dec 2016 23:27:48 +0000 (15:27 -0800)
"git push --dry-run --recurse-submodule=on-demand" wasn't
"--dry-run" in the submodules.

* bw/push-dry-run:
push: fix --dry-run to not push submodules
push: --dry-run updates submodules when --recurse-submodules=on-demand

1  2 
submodule.c
transport.c
diff --combined submodule.c
index 00dd655a5339b8e16c5b631d11c8072359430cb7,de20588e773d1e34e50fc7284ec598546ab60352..ece17315d671cf182f21c261d879c58f193cde09
@@@ -123,7 -123,9 +123,7 @@@ void stage_updated_gitmodules(void
  static int add_submodule_odb(const char *path)
  {
        struct strbuf objects_directory = STRBUF_INIT;
 -      struct alternate_object_database *alt_odb;
        int ret = 0;
 -      size_t alloc;
  
        ret = strbuf_git_path_submodule(&objects_directory, path, "objects/");
        if (ret)
                ret = -1;
                goto done;
        }
 -      /* avoid adding it twice */
 -      prepare_alt_odb();
 -      for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
 -              if (alt_odb->name - alt_odb->base == objects_directory.len &&
 -                              !strncmp(alt_odb->base, objects_directory.buf,
 -                                      objects_directory.len))
 -                      goto done;
 -
 -      alloc = st_add(objects_directory.len, 42); /* for "12/345..." sha1 */
 -      alt_odb = xmalloc(st_add(sizeof(*alt_odb), alloc));
 -      alt_odb->next = alt_odb_list;
 -      xsnprintf(alt_odb->base, alloc, "%s", objects_directory.buf);
 -      alt_odb->name = alt_odb->base + objects_directory.len;
 -      alt_odb->name[2] = '/';
 -      alt_odb->name[40] = '\0';
 -      alt_odb->name[41] = '\0';
 -      alt_odb_list = alt_odb;
 -
 -      /* add possible alternates from the submodule */
 -      read_info_alternates(objects_directory.buf, 0);
 +      add_to_alternates_memory(objects_directory.buf);
  done:
        strbuf_release(&objects_directory);
        return ret;
@@@ -371,9 -392,10 +371,9 @@@ static void show_submodule_header(FILE 
        }
  
  output_header:
 -      strbuf_addf(&sb, "%s%sSubmodule %s %s..", line_prefix, meta, path,
 -                      find_unique_abbrev(one->hash, DEFAULT_ABBREV));
 -      if (!fast_backward && !fast_forward)
 -              strbuf_addch(&sb, '.');
 +      strbuf_addf(&sb, "%s%sSubmodule %s ", line_prefix, meta, path);
 +      strbuf_add_unique_abbrev(&sb, one->hash, DEFAULT_ABBREV);
 +      strbuf_addstr(&sb, (fast_backward || fast_forward) ? ".." : "...");
        strbuf_add_unique_abbrev(&sb, two->hash, DEFAULT_ABBREV);
        if (message)
                strbuf_addf(&sb, " %s%s\n", message, reset);
@@@ -661,16 -683,17 +661,17 @@@ int find_unpushed_submodules(struct sha
        return needs_pushing->nr;
  }
  
- static int push_submodule(const char *path)
+ static int push_submodule(const char *path, int dry_run)
  {
        if (add_submodule_odb(path))
                return 1;
  
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
                struct child_process cp = CHILD_PROCESS_INIT;
-               const char *argv[] = {"push", NULL};
+               argv_array_push(&cp.args, "push");
+               if (dry_run)
+                       argv_array_push(&cp.args, "--dry-run");
  
-               cp.argv = argv;
                prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
                cp.no_stdin = 1;
        return 1;
  }
  
- int push_unpushed_submodules(struct sha1_array *commits, const char *remotes_name)
+ int push_unpushed_submodules(struct sha1_array *commits,
+                            const char *remotes_name,
+                            int dry_run)
  {
        int i, ret = 1;
        struct string_list needs_pushing = STRING_LIST_INIT_DUP;
        for (i = 0; i < needs_pushing.nr; i++) {
                const char *path = needs_pushing.items[i].string;
                fprintf(stderr, "Pushing submodule '%s'\n", path);
-               if (!push_submodule(path)) {
+               if (!push_submodule(path, dry_run)) {
                        fprintf(stderr, "Unable to push submodule '%s'\n", path);
                        ret = 0;
                }
diff --combined transport.c
index f48286905786a9492edd82adc3b633411dbce152,e0651a5bfc9cb01cab5fc15322c493a8ebb42a73..04e5d6623e39014622e0a185d37f8a456fd352e6
@@@ -307,9 -307,7 +307,9 @@@ void transport_update_tracking_ref(stru
        }
  }
  
 -static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
 +static void print_ref_status(char flag, const char *summary,
 +                           struct ref *to, struct ref *from, const char *msg,
 +                           int porcelain, int summary_width)
  {
        if (porcelain) {
                if (from)
                else
                        fprintf(stdout, "%s\n", summary);
        } else {
 -              fprintf(stderr, " %c %-*s ", flag, TRANSPORT_SUMMARY_WIDTH, summary);
 +              fprintf(stderr, " %c %-*s ", flag, summary_width, summary);
                if (from)
                        fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
                else
        }
  }
  
 -static void print_ok_ref_status(struct ref *ref, int porcelain)
 +static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_width)
  {
        if (ref->deletion)
 -              print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
 +              print_ref_status('-', "[deleted]", ref, NULL, NULL,
 +                               porcelain, summary_width);
        else if (is_null_oid(&ref->old_oid))
                print_ref_status('*',
                        (starts_with(ref->name, "refs/tags/") ? "[new tag]" :
                        "[new branch]"),
 -                      ref, ref->peer_ref, NULL, porcelain);
 +                      ref, ref->peer_ref, NULL, porcelain, summary_width);
        else {
                struct strbuf quickref = STRBUF_INIT;
                char type;
                strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash,
                                         DEFAULT_ABBREV);
  
 -              print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, porcelain);
 +              print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg,
 +                               porcelain, summary_width);
                strbuf_release(&quickref);
        }
  }
  
 -static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
 +static int print_one_push_status(struct ref *ref, const char *dest, int count,
 +                               int porcelain, int summary_width)
  {
        if (!count) {
                char *url = transport_anonymize_url(dest);
  
        switch(ref->status) {
        case REF_STATUS_NONE:
 -              print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
 +              print_ref_status('X', "[no match]", ref, NULL, NULL,
 +                               porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_NODELETE:
                print_ref_status('!', "[rejected]", ref, NULL,
 -                                               "remote does not support deleting refs", porcelain);
 +                               "remote does not support deleting refs",
 +                               porcelain, summary_width);
                break;
        case REF_STATUS_UPTODATE:
                print_ref_status('=', "[up to date]", ref,
 -                                               ref->peer_ref, NULL, porcelain);
 +                               ref->peer_ref, NULL, porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_NONFASTFORWARD:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "non-fast-forward", porcelain);
 +                               "non-fast-forward", porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_ALREADY_EXISTS:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "already exists", porcelain);
 +                               "already exists", porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_FETCH_FIRST:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "fetch first", porcelain);
 +                               "fetch first", porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_NEEDS_FORCE:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "needs force", porcelain);
 +                               "needs force", porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_STALE:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "stale info", porcelain);
 +                               "stale info", porcelain, summary_width);
                break;
        case REF_STATUS_REJECT_SHALLOW:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "new shallow roots not allowed", porcelain);
 +                               "new shallow roots not allowed",
 +                               porcelain, summary_width);
                break;
        case REF_STATUS_REMOTE_REJECT:
                print_ref_status('!', "[remote rejected]", ref,
 -                                               ref->deletion ? NULL : ref->peer_ref,
 -                                               ref->remote_status, porcelain);
 +                               ref->deletion ? NULL : ref->peer_ref,
 +                               ref->remote_status, porcelain, summary_width);
                break;
        case REF_STATUS_EXPECTING_REPORT:
                print_ref_status('!', "[remote failure]", ref,
 -                                               ref->deletion ? NULL : ref->peer_ref,
 -                                               "remote failed to report status", porcelain);
 +                               ref->deletion ? NULL : ref->peer_ref,
 +                               "remote failed to report status",
 +                               porcelain, summary_width);
                break;
        case REF_STATUS_ATOMIC_PUSH_FAILED:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 -                                               "atomic push failed", porcelain);
 +                               "atomic push failed", porcelain, summary_width);
                break;
        case REF_STATUS_OK:
 -              print_ok_ref_status(ref, porcelain);
 +              print_ok_ref_status(ref, porcelain, summary_width);
                break;
        }
  
        return 1;
  }
  
 +static int measure_abbrev(const struct object_id *oid, int sofar)
 +{
 +      char hex[GIT_SHA1_HEXSZ + 1];
 +      int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV);
 +
 +      return (w < sofar) ? sofar : w;
 +}
 +
 +int transport_summary_width(const struct ref *refs)
 +{
 +      int maxw = -1;
 +
 +      for (; refs; refs = refs->next) {
 +              maxw = measure_abbrev(&refs->old_oid, maxw);
 +              maxw = measure_abbrev(&refs->new_oid, maxw);
 +      }
 +      if (maxw < 0)
 +              maxw = FALLBACK_DEFAULT_ABBREV;
 +      return (2 * maxw + 3);
 +}
 +
  void transport_print_push_status(const char *dest, struct ref *refs,
                                  int verbose, int porcelain, unsigned int *reject_reasons)
  {
        int n = 0;
        unsigned char head_sha1[20];
        char *head;
 +      int summary_width = transport_summary_width(refs);
  
        head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL);
  
        if (verbose) {
                for (ref = refs; ref; ref = ref->next)
                        if (ref->status == REF_STATUS_UPTODATE)
 -                              n += print_one_push_status(ref, dest, n, porcelain);
 +                              n += print_one_push_status(ref, dest, n,
 +                                                         porcelain, summary_width);
        }
  
        for (ref = refs; ref; ref = ref->next)
                if (ref->status == REF_STATUS_OK)
 -                      n += print_one_push_status(ref, dest, n, porcelain);
 +                      n += print_one_push_status(ref, dest, n,
 +                                                 porcelain, summary_width);
  
        *reject_reasons = 0;
        for (ref = refs; ref; ref = ref->next) {
                if (ref->status != REF_STATUS_NONE &&
                    ref->status != REF_STATUS_UPTODATE &&
                    ref->status != REF_STATUS_OK)
 -                      n += print_one_push_status(ref, dest, n, porcelain);
 +                      n += print_one_push_status(ref, dest, n,
 +                                                 porcelain, summary_width);
                if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) {
                        if (head != NULL && !strcmp(head, ref->name))
                                *reject_reasons |= REJECT_NON_FF_HEAD;
@@@ -955,15 -921,18 +955,18 @@@ int transport_push(struct transport *tr
                                if (!is_null_oid(&ref->new_oid))
                                        sha1_array_append(&commits, ref->new_oid.hash);
  
-                       if (!push_unpushed_submodules(&commits, transport->remote->name)) {
+                       if (!push_unpushed_submodules(&commits,
+                                                     transport->remote->name,
+                                                     pretend)) {
                                sha1_array_clear(&commits);
                                die("Failed to push all needed submodules!");
                        }
                        sha1_array_clear(&commits);
                }
  
-               if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
-                             TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) {
+               if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) ||
+                    ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) &&
+                     !pretend)) && !is_bare_repository()) {
                        struct ref *ref = remote_refs;
                        struct string_list needs_pushing = STRING_LIST_INIT_DUP;
                        struct sha1_array commits = SHA1_ARRAY_INIT;
@@@ -1143,7 -1112,9 +1146,7 @@@ static int refs_from_alternate_cb(struc
        const struct ref *extra;
        struct alternate_refs_data *cb = data;
  
 -      e->name[-1] = '\0';
 -      other = xstrdup(real_path(e->base));
 -      e->name[-1] = '/';
 +      other = xstrdup(real_path(e->path));
        len = strlen(other);
  
        while (other[len-1] == '/')