Merge branch 'db/vcs-helper'
[git/git.git] / transport.c
index b654d71..4cb8077 100644 (file)
@@ -354,7 +354,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
 {
        const char **argv;
        int argc;
-       int err;
 
        if (flags & TRANSPORT_PUSH_MIRROR)
                return error("http transport does not support mirror mode");
@@ -374,20 +373,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
        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;
+       return !!run_command_v_opt(argv, RUN_GIT_CMD);
 }
 
 #endif
@@ -549,6 +535,21 @@ static int fetch_refs_via_pack(struct transport *transport,
        return (refs ? 0 : -1);
 }
 
+static int push_had_errors(struct ref *ref)
+{
+       for (; ref; ref = ref->next) {
+               switch (ref->status) {
+               case REF_STATUS_NONE:
+               case REF_STATUS_UPTODATE:
+               case REF_STATUS_OK:
+                       break;
+               default:
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 static int refs_pushed(struct ref *ref)
 {
        for (; ref; ref = ref->next) {
@@ -688,7 +689,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
 }
 
 static void print_push_status(const char *dest, struct ref *refs,
-                                                         int verbose, int porcelain)
+                             int verbose, int porcelain, int * nonfastforward)
 {
        struct ref *ref;
        int n = 0;
@@ -703,11 +704,14 @@ static void print_push_status(const char *dest, struct ref *refs,
                if (ref->status == REF_STATUS_OK)
                        n += print_one_push_status(ref, dest, n, porcelain);
 
+       *nonfastforward = 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);
+               if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
+                       *nonfastforward = 1;
        }
 }
 
@@ -760,6 +764,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
        args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
        args.use_thin_pack = data->thin;
        args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
+       args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
        args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
 
        ret = send_pack(&args, data->fd, data->conn, remote_refs,
@@ -863,7 +868,8 @@ int transport_set_option(struct transport *transport,
 }
 
 int transport_push(struct transport *transport,
-                  int refspec_nr, const char **refspec, int flags)
+                  int refspec_nr, const char **refspec, int flags,
+                  int * nonfastforward)
 {
        verify_remote_names(refspec_nr, refspec);
 
@@ -875,6 +881,7 @@ int transport_push(struct transport *transport,
                struct ref *local_refs = get_local_heads();
                int match_flags = MATCH_REFS_NONE;
                int verbose = flags & TRANSPORT_PUSH_VERBOSE;
+               int quiet = flags & TRANSPORT_PUSH_QUIET;
                int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
                int ret;
 
@@ -890,7 +897,10 @@ int transport_push(struct transport *transport,
 
                ret = transport->push_refs(transport, remote_refs, flags);
 
-               print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
+               if (!quiet || push_had_errors(remote_refs))
+                       print_push_status(transport->url, remote_refs,
+                                       verbose | porcelain, porcelain,
+                                       nonfastforward);
 
                if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
                        struct ref *ref;
@@ -898,7 +908,7 @@ int transport_push(struct transport *transport,
                                update_tracking_ref(transport->remote, ref, verbose);
                }
 
-               if (!ret && !refs_pushed(remote_refs))
+               if (!quiet && !ret && !refs_pushed(remote_refs))
                        fprintf(stderr, "Everything up-to-date\n");
                return ret;
        }
@@ -915,11 +925,12 @@ const struct ref *transport_get_remote_refs(struct transport *transport)
 int transport_fetch_refs(struct transport *transport, const struct ref *refs)
 {
        int rc;
-       int nr_heads = 0, nr_alloc = 0;
+       int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
        const struct ref **heads = NULL;
        const struct ref *rm;
 
        for (rm = refs; rm; rm = rm->next) {
+               nr_refs++;
                if (rm->peer_ref &&
                    !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1))
                        continue;
@@ -927,6 +938,19 @@ int transport_fetch_refs(struct transport *transport, const struct ref *refs)
                heads[nr_heads++] = rm;
        }
 
+       if (!nr_heads) {
+               /*
+                * When deepening of a shallow repository is requested,
+                * then local and remote refs are likely to still be equal.
+                * Just feed them all to the fetch method in that case.
+                * This condition shouldn't be met in a non-deepening fetch
+                * (see builtin-fetch.c:quickfetch()).
+                */
+               heads = xmalloc(nr_refs * sizeof(*heads));
+               for (rm = refs; rm; rm = rm->next)
+                       heads[nr_heads++] = rm;
+       }
+
        rc = transport->fetch(transport, nr_heads, heads);
        free(heads);
        return rc;