]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'js/simple-ipc-cygwin-socket-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 10 Nov 2021 23:01:20 +0000 (15:01 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Nov 2021 23:01:20 +0000 (15:01 -0800)
The way Cygwin emulates a unix-domain socket, on top of which the
simple-ipc mechanism is implemented, can race with the program on
the other side that wants to use the socket, and briefly make it
appear as a regular file before lstat(2) starts reporting it as a
socket.  We now have a workaround on the side that connects to a
unix domain socket.

* js/simple-ipc-cygwin-socket-fix:
  simple-ipc: work around issues with Cygwin's Unix socket emulation

builtin/gc.c
builtin/pull.c
t/t7601-merge-pull-config.sh

index 267093116019463f889b2aeff42ae57efe75c156..bcef6a4c8da71f54d923bbccc7a152a068e3b8c4 100644 (file)
@@ -1999,15 +1999,11 @@ static int schtasks_update_schedule(int run_maintenance, int fd)
                return schtasks_remove_tasks();
 }
 
-static int is_crontab_available(void)
+MAYBE_UNUSED
+static int check_crontab_process(const char *cmd)
 {
-       const char *cmd = "crontab";
-       int is_available;
        struct child_process child = CHILD_PROCESS_INIT;
 
-       if (get_schedule_cmd(&cmd, &is_available))
-               return is_available;
-
        strvec_split(&child.args, cmd);
        strvec_push(&child.args, "-l");
        child.no_stdin = 1;
@@ -2022,6 +2018,25 @@ static int is_crontab_available(void)
        return 1;
 }
 
+static int is_crontab_available(void)
+{
+       const char *cmd = "crontab";
+       int is_available;
+
+       if (get_schedule_cmd(&cmd, &is_available))
+               return is_available;
+
+#ifdef __APPLE__
+       /*
+        * macOS has cron, but it requires special permissions and will
+        * create a UI alert when attempting to run this command.
+        */
+       return 0;
+#else
+       return check_crontab_process(cmd);
+#endif
+}
+
 #define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"
 #define END_LINE "# END GIT MAINTENANCE SCHEDULE"
 
index efe4f4a81f944ea8178e959e6b4fab368ae2f9ae..127798ba84eaeeb3b1df26926c9675b744e8e589 100644 (file)
@@ -937,6 +937,33 @@ static int get_can_ff(struct object_id *orig_head,
        return ret;
 }
 
+/*
+ * Is orig_head a descendant of _all_ merge_heads?
+ * Unfortunately is_descendant_of() cannot be used as it asks
+ * if orig_head is a descendant of at least one of them.
+ */
+static int already_up_to_date(struct object_id *orig_head,
+                             struct oid_array *merge_heads)
+{
+       int i;
+       struct commit *ours;
+
+       ours = lookup_commit_reference(the_repository, orig_head);
+       for (i = 0; i < merge_heads->nr; i++) {
+               struct commit_list *list = NULL;
+               struct commit *theirs;
+               int ok;
+
+               theirs = lookup_commit_reference(the_repository, &merge_heads->oid[i]);
+               commit_list_insert(theirs, &list);
+               ok = repo_is_descendant_of(the_repository, ours, list);
+               free_commit_list(list);
+               if (!ok)
+                       return 0;
+       }
+       return 1;
+}
+
 static void show_advice_pull_non_ff(void)
 {
        advise(_("You have divergent branches and need to specify how to reconcile them.\n"
@@ -1078,7 +1105,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
 
        /* ff-only takes precedence over rebase */
        if (opt_ff && !strcmp(opt_ff, "--ff-only")) {
-               if (!can_ff)
+               if (!can_ff && !already_up_to_date(&orig_head, &merge_heads))
                        die_ff_impossible();
                opt_rebase = REBASE_FALSE;
        }
index 1f652f433ee276b1420324f6609ae51c5b02863c..6275641b9c2459e69ec201189d9e202fc8f937fe 100755 (executable)
@@ -2,7 +2,7 @@
 
 test_description='git merge
 
-Testing pull.* configuration parsing.'
+Testing pull.* configuration parsing and other things.'
 
 . ./test-lib.sh
 
@@ -387,6 +387,20 @@ test_expect_success 'pull prevents non-fast-forward with "only" in pull.ff' '
        test_must_fail git pull . c3
 '
 
+test_expect_success 'already-up-to-date pull succeeds with "only" in pull.ff' '
+       git reset --hard c1 &&
+       test_config pull.ff only &&
+       git pull . c0 &&
+       test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
+test_expect_success 'already-up-to-date pull/rebase succeeds with "only" in pull.ff' '
+       git reset --hard c1 &&
+       test_config pull.ff only &&
+       git -c pull.rebase=true pull . c0 &&
+       test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
 test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
        git reset --hard c1 &&
        git config pull.twohead ours &&