Merge branch 'jc/po-pritime-fix'
authorJunio C Hamano <gitster@pobox.com>
Fri, 21 Jul 2017 21:57:36 +0000 (14:57 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Jul 2017 21:57:37 +0000 (14:57 -0700)
We started using "%" PRItime, imitating "%" PRIuMAX and friends, as
a way to format the internal timestamp value, but this does not
play well with gettext(1) i18n framework, and causes "make pot"
that is run by the l10n coordinator to create a broken po/git.pot
file. This is a possible workaround for that problem.

* jc/po-pritime-fix:
Makefile: help gettext tools to cope with our custom PRItime format

Documentation/RelNotes/2.14.0.txt
Makefile
alias.c
git-p4.py
sha1_file.c
t/t1300-repo-config.sh
t/t9831-git-p4-triggers.sh [new file with mode: 0755]
t/test-lib-functions.sh
index 2f3879fe96f908f075022a037de46f7bc4a66765..0595a369361dea0f19ee617171a8a7f64338f0f2 100644 (file)
@@ -117,6 +117,11 @@ UI, Workflows & Features
  * "git pull --rebase --recurse-submodules" learns to rebase the
    branch in the submodules to an updated base.
 
+ * "git log" learned -P as a synonym for --perl-regexp, "git grep"
+   already had such a synonym.
+
+ * "git log" didn't understand --regexp-ignore-case when combined with
+   --perl-regexp. This has been fixed.
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -230,6 +235,18 @@ Performance, Internal Implementation, Development Support etc.
    behaviour of the comparison function can be specified at the time a
    hashmap is initialized.
 
+ * The "collision detecting" SHA-1 implementation shipped with 2.13 is
+   now integrated into git.git as a submodule (the first submodule to
+   ship with git.git). Clone git.git with --recurse-submodules to get
+   it. For now a non-submodule copy of the same code is also shipped
+   as part of the tree.
+
+ * A recent update made it easier to use "-fsanitize=" option while
+   compiling but supported only one sanitize option.  Allow more than
+   one to be combined, joined with a comma, like "make SANITIZE=foo,bar".
+
+ * Use "p4 -G" to make "p4 changes" output more Python-friendly
+   to parse.
 
 Also contains various documentation updates and code clean-ups.
 
@@ -487,9 +504,14 @@ notes for details).
    early part also under the GC lock.
    (merge c45af94dbc jk/gc-pre-detach-under-hook later to maint).
 
+ * A recent update broke an alias that contained an uppercase letter.
+   (merge 643df7e234 js/alias-case-sensitivity later to maint).
+
  * Other minor doc, test and build updates and code cleanups.
    (merge 3f9c637ec7 pw/unquote-path-in-git-pm later to maint).
    (merge 5053313562 rs/urlmatch-cleanup later to maint).
    (merge 42c78a216e rs/use-div-round-up later to maint).
    (merge 5e8d2729ae rs/wt-status-cleanup later to maint).
    (merge 01826066b0 ks/fix-rebase-doc-picture later to maint).
+   (merge f7f6dc340e jk/test-copy-bytes-fix later to maint).
+   (merge 9fb9495dae ew/fd-cloexec-fix later to maint).
index b1ff6fad198f6f778f1e07c58558c30bf5b45003..461c845d33cbc5f201096ea4b3e1048492cb0a6a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1022,10 +1022,15 @@ ifdef DEVELOPER
 CFLAGS += $(DEVELOPER_CFLAGS)
 endif
 
+comma := ,
+empty :=
+space := $(empty) $(empty)
+
 ifdef SANITIZE
+SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))
 BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)
 BASIC_CFLAGS += -fno-omit-frame-pointer
-ifeq ($(SANITIZE),undefined)
+ifneq ($(filter undefined,$(SANITIZERS)),)
 BASIC_CFLAGS += -DNO_UNALIGNED_LOADS
 endif
 endif
diff --git a/alias.c b/alias.c
index 39f622e4141576b1170131f6c4b14316becb1a71..bf146e526329309df360b9f1028ca2f767743efa 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -11,7 +11,7 @@ static int config_alias_cb(const char *key, const char *value, void *d)
        struct config_alias_data *data = d;
        const char *p;
 
-       if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
+       if (skip_prefix(key, "alias.", &p) && !strcasecmp(p, data->alias))
                return git_config_string((const char **)&data->v, key, value);
 
        return 0;
index 8d151da91b9699e804f4d28b865af7f44138bfc1..2fa581789c5d9d4dd967e1783c513d64660f8a9c 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -313,7 +313,7 @@ def p4_move(src, dest):
     p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
 
 def p4_last_change():
-    results = p4CmdList(["changes", "-m", "1"])
+    results = p4CmdList(["changes", "-m", "1"], skip_info=True)
     return int(results[0]['change'])
 
 def p4_describe(change):
@@ -321,7 +321,7 @@ def p4_describe(change):
        the presence of field "time".  Return a dict of the
        results."""
 
-    ds = p4CmdList(["describe", "-s", str(change)])
+    ds = p4CmdList(["describe", "-s", str(change)], skip_info=True)
     if len(ds) != 1:
         die("p4 describe -s %d did not return 1 result: %s" % (change, str(ds)))
 
@@ -509,7 +509,7 @@ def isModeExec(mode):
 def isModeExecChanged(src_mode, dst_mode):
     return isModeExec(src_mode) != isModeExec(dst_mode)
 
-def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
+def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False):
 
     if isinstance(cmd,basestring):
         cmd = "-G " + cmd
@@ -545,6 +545,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
     try:
         while True:
             entry = marshal.load(p4.stdout)
+            if skip_info:
+                if 'code' in entry and entry['code'] == 'info':
+                    continue
             if cb is not None:
                 cb(entry)
             else:
@@ -879,8 +882,12 @@ def p4ChangesForPaths(depotPaths, changeRange, requestedBlockSize):
             cmd += ["%s...@%s" % (p, revisionRange)]
 
         # Insert changes in chronological order
-        for line in reversed(p4_read_pipe_lines(cmd)):
-            changes.add(int(line.split(" ")[1]))
+        for entry in reversed(p4CmdList(cmd)):
+            if entry.has_key('p4ExitCode'):
+                die('Error retrieving changes descriptions ({})'.format(entry['p4ExitCode']))
+            if not entry.has_key('change'):
+                continue
+            changes.add(int(entry['change']))
 
         if not block_size:
             break
@@ -1526,37 +1533,62 @@ def prepareSubmitTemplate(self, changelist=None):
 
         [upstream, settings] = findUpstreamBranchPoint()
 
-        template = ""
+        template = """\
+# A Perforce Change Specification.
+#
+#  Change:      The change number. 'new' on a new changelist.
+#  Date:        The date this specification was last modified.
+#  Client:      The client on which the changelist was created.  Read-only.
+#  User:        The user who created the changelist.
+#  Status:      Either 'pending' or 'submitted'. Read-only.
+#  Type:        Either 'public' or 'restricted'. Default is 'public'.
+#  Description: Comments about the changelist.  Required.
+#  Jobs:        What opened jobs are to be closed by this changelist.
+#               You may delete jobs from this list.  (New changelists only.)
+#  Files:       What opened files from the default changelist are to be added
+#               to this changelist.  You may delete files from this list.
+#               (New changelists only.)
+"""
+        files_list = []
         inFilesSection = False
+        change_entry = None
         args = ['change', '-o']
         if changelist:
             args.append(str(changelist))
-
-        for line in p4_read_pipe_lines(args):
-            if line.endswith("\r\n"):
-                line = line[:-2] + "\n"
-            if inFilesSection:
-                if line.startswith("\t"):
-                    # path starts and ends with a tab
-                    path = line[1:]
-                    lastTab = path.rfind("\t")
-                    if lastTab != -1:
-                        path = path[:lastTab]
-                        if settings.has_key('depot-paths'):
-                            if not [p for p in settings['depot-paths']
-                                    if p4PathStartsWith(path, p)]:
-                                continue
-                        else:
-                            if not p4PathStartsWith(path, self.depotPath):
-                                continue
+        for entry in p4CmdList(args):
+            if not entry.has_key('code'):
+                continue
+            if entry['code'] == 'stat':
+                change_entry = entry
+                break
+        if not change_entry:
+            die('Failed to decode output of p4 change -o')
+        for key, value in change_entry.iteritems():
+            if key.startswith('File'):
+                if settings.has_key('depot-paths'):
+                    if not [p for p in settings['depot-paths']
+                            if p4PathStartsWith(value, p)]:
+                        continue
                 else:
-                    inFilesSection = False
-            else:
-                if line.startswith("Files:"):
-                    inFilesSection = True
-
-            template += line
-
+                    if not p4PathStartsWith(value, self.depotPath):
+                        continue
+                files_list.append(value)
+                continue
+        # Output in the order expected by prepareLogMessage
+        for key in ['Change', 'Client', 'User', 'Status', 'Description', 'Jobs']:
+            if not change_entry.has_key(key):
+                continue
+            template += '\n'
+            template += key + ':'
+            if key == 'Description':
+                template += '\n'
+            for field_line in change_entry[key].splitlines():
+                template += '\t'+field_line+'\n'
+        if len(files_list) > 0:
+            template += '\n'
+            template += 'Files:\n'
+        for path in files_list:
+            template += '\t'+path+'\n'
         return template
 
     def edit_template(self, template_file):
index fca165f13ccd145c184eaa8601bd60156d5b073b..b60ae15f7068c157df6407933ea7ee94a53f0640 100644 (file)
@@ -1684,14 +1684,14 @@ int git_open_cloexec(const char *name, int flags)
                fd = open(name, flags | o_cloexec);
        }
 
-#if defined(F_GETFL) && defined(F_SETFL) && defined(FD_CLOEXEC)
+#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
        {
                static int fd_cloexec = FD_CLOEXEC;
 
                if (!o_cloexec && 0 <= fd && fd_cloexec) {
                        /* Opened w/o O_CLOEXEC?  try with fcntl(2) to add it */
-                       int flags = fcntl(fd, F_GETFL);
-                       if (fcntl(fd, F_SETFL, flags | fd_cloexec))
+                       int flags = fcntl(fd, F_GETFD);
+                       if (fcntl(fd, F_SETFD, flags | fd_cloexec))
                                fd_cloexec = 0;
                }
        }
index a37ef0422212eafdae4b4c0fae9e28d4a183117f..364a537000bbbdd43047bd3f9c52c950a96dcbda 100755 (executable)
@@ -1075,6 +1075,13 @@ test_expect_success 'git -c works with aliases of builtins' '
        test_cmp expect actual
 '
 
+test_expect_success 'aliases can be CamelCased' '
+       test_config alias.CamelCased "rev-parse HEAD" &&
+       git CamelCased >out &&
+       git rev-parse HEAD >expect &&
+       test_cmp expect out
+'
+
 test_expect_success 'git -c does not split values on equals' '
        echo "value with = in it" >expect &&
        git -c core.foo="value with = in it" config core.foo >actual &&
diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh
new file mode 100755 (executable)
index 0000000..bbcf14c
--- /dev/null
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+test_description='git p4 with server triggers'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d' '
+       start_p4d
+'
+
+test_expect_success 'init depot' '
+       (
+               cd "$cli" &&
+               echo file1 >file1 &&
+               p4 add file1 &&
+               p4 submit -d "change 1"
+               echo file2 >file2 &&
+               p4 add file2 &&
+               p4 submit -d "change 2"
+       )
+'
+
+test_expect_success 'clone with extra info lines from verbose p4 trigger' '
+       test_when_finished cleanup_git &&
+       (
+               p4 triggers -i <<-EOF
+               Triggers: p4triggertest-command command pre-user-change "echo verbose trigger"
+               EOF
+       ) &&
+       (
+               p4 change -o |  grep -s "verbose trigger"
+       ) &&
+       git p4 clone --dest="$git" //depot/@all &&
+       (
+               p4 triggers -i <<-EOF
+               Triggers:
+               EOF
+       )
+'
+
+test_expect_success 'import with extra info lines from verbose p4 trigger' '
+       test_when_finished cleanup_git &&
+       (
+               cd "$cli" &&
+               echo file3 >file3 &&
+               p4 add file3 &&
+               p4 submit -d "change 3"
+       ) &&
+       (
+               p4 triggers -i <<-EOF
+               Triggers: p4triggertest-command command pre-user-describe "echo verbose trigger"
+               EOF
+       ) &&
+       (
+               p4 describe 1 |  grep -s "verbose trigger"
+       ) &&
+       git p4 clone --dest="$git" //depot/@all &&
+       (
+               cd "$git" &&
+               git p4 sync
+       )&&
+       (
+               p4 triggers -i <<-EOF
+               Triggers:
+               EOF
+       )
+'
+
+test_expect_success 'submit description with extra info lines from verbose p4 change trigger' '
+       test_when_finished cleanup_git &&
+       (
+               p4 triggers -i <<-EOF
+               Triggers: p4triggertest-command command pre-user-change "echo verbose trigger"
+               EOF
+       ) &&
+       (
+               p4 change -o |  grep -s "verbose trigger"
+       ) &&
+       git p4 clone --dest="$git" //depot &&
+       (
+               cd "$git" &&
+               git config git-p4.skipSubmitEdit true &&
+               echo file4 >file4 &&
+               git add file4 &&
+               git commit -m file4 &&
+               git p4 submit
+       ) &&
+       (
+               p4 triggers -i <<-EOF
+               Triggers:
+               EOF
+       ) &&
+       (
+               cd "$cli" &&
+               test_path_is_file file4
+       )
+'
+
+test_expect_success 'kill p4d' '
+       kill_p4d
+'
+
+test_done
index db622c3555dcbf7f66b45c05df5279b6db6b2a9e..50a9a1d1c49e719d0ee65435b05171747e065259 100644 (file)
@@ -999,6 +999,7 @@ test_copy_bytes () {
                        my $s;
                        my $nread = sysread(STDIN, $s, $len);
                        die "cannot read: $!" unless defined($nread);
+                       last unless $nread;
                        print $s;
                        $len -= $nread;
                }