Merge branch 'master' into sp/mmap
authorJunio C Hamano <junkio@cox.net>
Sun, 31 Dec 2006 06:42:43 +0000 (22:42 -0800)
committerJunio C Hamano <junkio@cox.net>
Sun, 31 Dec 2006 06:42:43 +0000 (22:42 -0800)
* master:
Documentation/config.txt (and repo-config manpage): mark-up fix.
Teach Git how to parse standard power of 2 suffixes.
Use /dev/null for update hook stdin.
Redirect update hook stdout to stderr.
Remove unnecessary argc parameter from run_command_v.
Automatically detect a bare git repository.
Replace "GIT_DIR" with GIT_DIR_ENVIRONMENT.
Use PATH_MAX constant for --bare.
Force core.filemode to false on Cygwin.
Fix formatting for urls section of fetch, pull, and push manpages
Fix yet another subtle xdl_merge() bug
i18n: drop "encoding" header in the output after re-coding.
commit-tree: cope with different ways "utf-8" can be spelled.
Move commit reencoding parameter parsing to revision.c
Documentation: minor rewording for git-log and git-show pages.
Documentation: i18n commit log message notes.
t3900: test log --encoding=none
commit re-encoding: fix confusion between no and default conversion.

27 files changed:
Documentation/config.txt
Documentation/git-commit-tree.txt
Documentation/git-commit.txt
Documentation/git-log.txt
Documentation/git-repo-config.txt
Documentation/git-rev-list.txt
Documentation/git-show.txt
Documentation/i18n.txt [new file with mode: 0644]
Documentation/pretty-formats.txt
Documentation/urls.txt
Makefile
builtin-commit-tree.c
builtin-init-db.c
builtin-push.c
commit.c
config.c
git.c
receive-pack.c
revision.c
run-command.c
run-command.h
setup.c
t/t1300-repo-config.sh
t/t3900-i18n-commit.sh
utf8.c
utf8.h
xdiff/xmerge.c
index d71653dc65b285806096ffa315c15f62d164c8e3..744484b98230457b8cc79063c4ffdeec4cac7b0c 100644 (file)
@@ -82,13 +82,13 @@ core.logAllRefUpdates::
        only when the file exists.  If this configuration
        variable is set to true, missing "$GIT_DIR/logs/<ref>"
        file is automatically created for branch heads.
-
-       This information can be used to determine what commit
-       was the tip of a branch "2 days ago".
-
-       This value is true by default in a repository that has
-       a working directory associated with it, and false by
-       default in a bare repository.
++
+This information can be used to determine what commit
+was the tip of a branch "2 days ago".
++
+This value is true by default in a repository that has
+a working directory associated with it, and false by
+default in a bare repository.
 
 core.repositoryFormatVersion::
        Internal variable identifying the repository format and layout
index 41d1a1c4b340b17a545feebe9877def8b009933f..77ba96ed8a4820354ef6d2ff4265660385289f3d 100644 (file)
@@ -81,6 +81,11 @@ Your parents must have hated you!::
 Your sysadmin must hate you!::
     The password(5) name field is longer than a giant static buffer.
 
+Discussion
+----------
+
+include::i18n.txt[]
+
 See Also
 --------
 gitlink:git-write-tree[1]
index 0b74cd708ecaa63ccc19d2db40790b315539ce8b..a7adf24fa5a601f372099988c1fedfb929ceaab1 100644 (file)
@@ -223,6 +223,11 @@ should be recorded as a single commit.  In fact, the command
 refuses to run when given pathnames (but see `-i` option).
 
 
+DISCUSSION
+----------
+
+include::i18n.txt[]
+
 ENVIRONMENT VARIABLES
 ---------------------
 The command specified by either the VISUAL or EDITOR environment
index 79643ac928b05b4a97a09a5adfb67b1b4a2b832c..e9f746bbd4cebde9d8f5b90dd8fea6a2a610b140 100644 (file)
@@ -31,7 +31,9 @@ include::pretty-formats.txt[]
        Limits the number of commits to show.
 
 <since>..<until>::
-       Show only commits between the named two commits.
+       Show only commits between the named two commits.  When
+       either <since> or <until> is omitted, it defaults to
+       `HEAD`, i.e. the tip of the current branch.
 
 -p::
        Show the change the commit introduces in a patch form.
@@ -63,6 +65,12 @@ git log -r --name-status release..test::
        in the "release" branch, along with the list of paths
        each commit modifies.
 
+Discussion
+----------
+
+include::i18n.txt[]
+
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
index b379ec5075981347e75d0795e44e57620d89399b..c55a8ba0dcfc63110920bf6b5e8db91732d11853 100644 (file)
@@ -87,7 +87,10 @@ OPTIONS
        git-repo-config will ensure that the output is "true" or "false"
 
 --int::
-       git-repo-config will ensure that the output is a simple decimal number
+       git-repo-config will ensure that the output is a simple
+       decimal number.  An optional value suffix of 'k', 'm', or 'g'
+       in the config file will cause the value to be multiplied
+       by 1024, 1048576, or 1073741824 prior to output.
 
 
 ENVIRONMENT
index 9e0dcf8d3fef2495da4940ce662a46cc8a2bf621..86c94e7dfd257f5a7eff5c9d5aa4540a41128864 100644 (file)
@@ -21,6 +21,7 @@ SYNOPSIS
             [ \--stdin ]
             [ \--topo-order ]
             [ \--parents ]
+            [ \--encoding[=<encoding>] ]
             [ \--(author|committer|grep)=<pattern> ]
             [ [\--objects | \--objects-edge] [ \--unpacked ] ]
             [ \--pretty | \--header ]
index 98dea6125da78fa74800925b57dad2f002b1d6f6..c210b9af6bb4ce09d061e24715b07cd64887d54c 100644 (file)
@@ -30,8 +30,8 @@ This manual page describes only the most frequently used options.
 
 OPTIONS
 -------
-<commitid>::
-       ID of the commit to show.
+<object>::
+       The name of the object to show.
 
 include::pretty-formats.txt[]
 
@@ -40,7 +40,8 @@ EXAMPLES
 --------
 
 git show v1.0.0::
-       Shows the tag `v1.0.0`.
+       Shows the tag `v1.0.0`, along with the object the tags
+       points at.
 
 git show v1.0.0^{tree}::
        Shows the tree pointed to by the tag `v1.0.0`.
@@ -54,10 +55,16 @@ git show master:Makefile master:t/Makefile
        Concatenates the contents of said Makefiles in the head
        of the branch `master`.
 
+Discussion
+----------
+
+include::i18n.txt[]
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <junkio@cox.net>
+Junio C Hamano <junkio@cox.net>.  Significantly enhanced by
+Johannes Schindelin <Johannes.Schindelin@gmx.de>.
 
 
 Documentation
diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
new file mode 100644 (file)
index 0000000..b4cbb38
--- /dev/null
@@ -0,0 +1,57 @@
+At the core level, git is character encoding agnostic.
+
+ - The pathnames recorded in the index and in the tree objects
+   are treated as uninterpreted sequences of non-NUL bytes.
+   What readdir(2) returns are what are recorded and compared
+   with the data git keeps track of, which in turn are expected
+   to be what lstat(2) and creat(2) accepts.  There is no such
+   thing as pathname encoding translation.
+
+ - The contents of the blob objects are uninterpreted sequence
+   of bytes.  There is no encoding translation at the core
+   level.
+
+ - The commit log messages are uninterpreted sequence of non-NUL
+   bytes.
+
+Although we encourage that the commit log messages are encoded
+in UTF-8, both the core and git Porcelain are designed not to
+force UTF-8 on projects.  If all participants of a particular
+project find it more convenient to use legacy encodings, git
+does not forbid it.  However, there are a few things to keep in
+mind.
+
+. `git-commit-tree` (hence, `git-commit` which uses it) issues
+  an warning if the commit log message given to it does not look
+  like a valid UTF-8 string, unless you explicitly say your
+  project uses a legacy encoding.  The way to say this is to
+  have core.commitencoding in `.git/config` file, like this:
++
+------------
+[core]
+       commitencoding = ISO-8859-1
+------------
++
+Commit objects created with the above setting record the value
+of `core.commitencoding` in its `encoding` header.  This is to
+help other people who look at them later.  Lack of this header
+implies that the commit log message is encoded in UTF-8.
+
+. `git-log`, `git-show` and friends looks at the `encoding`
+  header of a commit object, and tries to re-code the log
+  message into UTF-8 unless otherwise specified.  You can
+  specify the desired output encoding with
+  `core.logoutputencoding` in `.git/config` file, like this:
++
+------------
+[core]
+       logoutputencoding = ISO-8859-1
+------------
++
+If you do not have this configuration variable, the value of
+`core.commitencoding` is used instead.
+
+Note that we deliberately chose not to re-code the commit log
+message when a commit is made to force UTF-8 at the commit
+object level, because re-coding to UTF-8 is not necessarily a
+reversible operation.
index 996f6289031a4535a29579f3111998856eb31bfd..fb0b0b95829e0fc1aa98019554ce12e9b45d1f63 100644 (file)
@@ -76,3 +76,10 @@ displayed in full, regardless of whether --abbrev or
 --no-abbrev are used, and 'parents' information show the
 true parent commits, without taking grafts nor history
 simplification into account.
+
+--encoding[=<encoding>]::
+       The commit objects record the encoding used for the log message
+       in their encoding header; this option can be used to tell the
+       command to re-code the commit log message in the encoding
+       preferred by the user.  For non plumbing commands this
+       defaults to UTF-8.
index 670827c323fe276124ba1a84d59386771db868f1..870c95073bbbb74e6d40ea1dd5dc642410bc9153 100644 (file)
@@ -40,9 +40,11 @@ In addition to the above, as a short-hand, the name of a
 file in `$GIT_DIR/remotes` directory can be given; the
 named file should be in the following format:
 
-       URL: one of the above URL format
-       Push: <refspec>
-       Pull: <refspec>
+------------
+URL: one of the above URL format
+Push: <refspec>
+Pull: <refspec>
+------------
 
 Then such a short-hand is specified in place of
 <repository> without <refspec> parameters on the command
@@ -54,10 +56,12 @@ be specified for additional branch mappings.
 Or, equivalently, in the `$GIT_DIR/config` (note the use
 of `fetch` instead of `Pull:`):
 
+------------
 [remote "<remote>"]
        url = <url>
        push = <refspec>
        fetch = <refspec>
+------------
 
 The name of a file in `$GIT_DIR/branches` directory can be
 specified as an older notation short-hand; the named
@@ -68,10 +72,15 @@ name of remote head (URL fragment notation).
 without the fragment is equivalent to have this in the
 corresponding file in the `$GIT_DIR/remotes/` directory.
 
-       URL: <url>
-       Pull: refs/heads/master:<remote>
+------------
+URL: <url>
+Pull: refs/heads/master:<remote>
+------------
+
 
 while having `<url>#<head>` is equivalent to
 
-       URL: <url>
-       Pull: refs/heads/<head>:<remote>
+------------
+URL: <url>
+Pull: refs/heads/<head>:<remote>
+------------
index 93dc4948d3cd6b655c2e0c630892e67b9ae656eb..fa1a02289c06630274eebbed25b022c4cfeea28b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,9 @@ all:
 # Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is
 # generally faster on your platform than accessing the working directory.
 #
+# Define NO_TRUSTABLE_FILEMODE if your filesystem may claim to support
+# the executable mode bit, but doesn't really do so.
+#
 # Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
 #
 # Define NO_SOCKADDR_STORAGE if your platform does not have struct
@@ -361,6 +364,7 @@ ifeq ($(uname_O),Cygwin)
        NEEDS_LIBICONV = YesPlease
        NO_C99_FORMAT = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
+       NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
        # There are conflicting reports about this.
        # On some boxes NO_MMAP is needed, and not so elsewhere.
        # Try commenting this out if you suspect MMAP is more efficient
@@ -521,6 +525,9 @@ endif
 ifdef NO_FAST_WORKING_DIRECTORY
        BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
 endif
+ifdef NO_TRUSTABLE_FILEMODE
+       BASIC_CFLAGS += -DNO_TRUSTABLE_FILEMODE
+endif
 ifdef NO_IPV6
        BASIC_CFLAGS += -DNO_IPV6
 endif
index 146aaffd282987454c0910477cfe7a047f478e94..0651e5927e836d22246d84020576ccb3069b6c5d 100644 (file)
@@ -119,8 +119,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
        }
 
        /* Not having i18n.commitencoding is the same as having utf-8 */
-       encoding_is_utf8 = (!git_commit_encoding ||
-                           !strcmp(git_commit_encoding, "utf-8"));
+       encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
 
        init_buffer(&buffer, &size);
        add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
index 01f366ad0bf5860aaf9123ef5d5653c612871a9f..97fd82ff0664aa9a79cf1ace20dac1a5c0064743 100644 (file)
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/"
 #endif
 
+#ifdef NO_TRUSTABLE_FILEMODE
+#define TEST_FILEMODE 0
+#else
+#define TEST_FILEMODE 1
+#endif
+
 static void safe_create_dir(const char *dir, int share)
 {
        if (mkdir(dir, 0777) < 0) {
@@ -175,6 +181,7 @@ static int create_default_files(const char *git_dir, const char *template_path)
        struct stat st1;
        char repo_version_string[10];
        int reinit;
+       int filemode;
 
        if (len > sizeof(path)-50)
                die("insane git directory %s", git_dir);
@@ -236,14 +243,14 @@ static int create_default_files(const char *git_dir, const char *template_path)
        strcpy(path + len, "config");
 
        /* Check filemode trustability */
-       if (!lstat(path, &st1)) {
+       filemode = TEST_FILEMODE;
+       if (TEST_FILEMODE && !lstat(path, &st1)) {
                struct stat st2;
-               int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
+               filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
                                !lstat(path, &st2) &&
                                st1.st_mode != st2.st_mode);
-               git_config_set("core.filemode",
-                              filemode ? "true" : "false");
        }
+       git_config_set("core.filemode", filemode ? "true" : "false");
 
        /* Enable logAllRefUpdates if a working tree is attached */
        if (!is_bare_git_dir(git_dir))
index b7412e82937a240776cdda07da05797b0b2acb0b..7a3d2bb06416219a41cf6a0757cf3d03a56ef0da 100644 (file)
@@ -275,7 +275,7 @@ static int do_push(const char *repo)
                argv[dest_argc] = NULL;
                if (verbose)
                        fprintf(stderr, "Pushing to %s\n", dest);
-               err = run_command_v(argc, argv);
+               err = run_command_v(argv);
                if (!err)
                        continue;
                switch (err) {
index eb06afbbe0f00ac4f553e37c50eca290418a7907..afdf27eeceb76f4f3842ba09b48d07bc218846d6 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -624,6 +624,48 @@ static char *get_header(const struct commit *commit, const char *key)
        }
 }
 
+static char *replace_encoding_header(char *buf, char *encoding)
+{
+       char *encoding_header = strstr(buf, "\nencoding ");
+       char *end_of_encoding_header;
+       int encoding_header_pos;
+       int encoding_header_len;
+       int new_len;
+       int need_len;
+       int buflen = strlen(buf) + 1;
+
+       if (!encoding_header)
+               return buf; /* should not happen but be defensive */
+       encoding_header++;
+       end_of_encoding_header = strchr(encoding_header, '\n');
+       if (!end_of_encoding_header)
+               return buf; /* should not happen but be defensive */
+       end_of_encoding_header++;
+
+       encoding_header_len = end_of_encoding_header - encoding_header;
+       encoding_header_pos = encoding_header - buf;
+
+       if (is_encoding_utf8(encoding)) {
+               /* we have re-coded to UTF-8; drop the header */
+               memmove(encoding_header, end_of_encoding_header,
+                       buflen - (encoding_header_pos + encoding_header_len));
+               return buf;
+       }
+       new_len = strlen(encoding);
+       need_len = new_len + strlen("encoding \n");
+       if (encoding_header_len < need_len) {
+               buf = xrealloc(buf, buflen + (need_len - encoding_header_len));
+               encoding_header = buf + encoding_header_pos;
+               end_of_encoding_header = encoding_header + encoding_header_len;
+       }
+       memmove(end_of_encoding_header + (need_len - encoding_header_len),
+               end_of_encoding_header,
+               buflen - (encoding_header_pos + encoding_header_len));
+       memcpy(encoding_header + 9, encoding, strlen(encoding));
+       encoding_header[9 + new_len] = '\n';
+       return buf;
+}
+
 static char *logmsg_reencode(const struct commit *commit)
 {
        char *encoding;
@@ -633,6 +675,8 @@ static char *logmsg_reencode(const struct commit *commit)
                                 : git_commit_encoding);
 
        if (!output_encoding)
+               output_encoding = "utf-8";
+       else if (!*output_encoding)
                return NULL;
        encoding = get_header(commit, "encoding");
        if (!encoding || !strcmp(encoding, output_encoding)) {
@@ -640,6 +684,9 @@ static char *logmsg_reencode(const struct commit *commit)
                return NULL;
        }
        out = reencode_string(commit->buffer, output_encoding, encoding);
+       if (out)
+               out = replace_encoding_header(out, output_encoding);
+
        free(encoding);
        if (!out)
                return NULL;
index 2e0d5a8681c1167b178a355782c90149adc42d9f..5cbd130be2664258b488d8b4ca914550e10906a0 100644 (file)
--- a/config.c
+++ b/config.c
@@ -238,6 +238,12 @@ int git_config_int(const char *name, const char *value)
                int val = strtol(value, &end, 0);
                if (!*end)
                        return val;
+               if (!strcasecmp(end, "k"))
+                       return val * 1024;
+               if (!strcasecmp(end, "m"))
+                       return val * 1024 * 1024;
+               if (!strcasecmp(end, "g"))
+                       return val * 1024 * 1024 * 1024;
        }
        die("bad config value for '%s' in %s", name, config_file_name);
 }
diff --git a/git.c b/git.c
index 50ebd869ad47cb2803a5a1e581442d7e72842034..c82ca458e47186cd926dc83030cb7a6c8a697e8d 100644 (file)
--- a/git.c
+++ b/git.c
@@ -63,14 +63,14 @@ static int handle_options(const char*** argv, int* argc)
                                fprintf(stderr, "No directory given for --git-dir.\n" );
                                usage(git_usage_string);
                        }
-                       setenv("GIT_DIR", (*argv)[1], 1);
+                       setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
                        (*argv)++;
                        (*argc)--;
                } else if (!strncmp(cmd, "--git-dir=", 10)) {
-                       setenv("GIT_DIR", cmd + 10, 1);
+                       setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
                } else if (!strcmp(cmd, "--bare")) {
-                       static char git_dir[1024];
-                       setenv("GIT_DIR", getcwd(git_dir, 1024), 1);
+                       static char git_dir[PATH_MAX+1];
+                       setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 1);
                } else {
                        fprintf(stderr, "Unknown option: %s\n", cmd);
                        usage(git_usage_string);
index 59b682c03af53fbfe600d063fa832f874440493c..c176d8fd008ad858a1e60e19e7bf3ea14d735eb5 100644 (file)
@@ -73,7 +73,9 @@ static int run_update_hook(const char *refname,
 
        if (access(update_hook, X_OK) < 0)
                return 0;
-       code = run_command(update_hook, refname, old_hex, new_hex, NULL);
+       code = run_command_opt(RUN_COMMAND_NO_STDIN
+               | RUN_COMMAND_STDOUT_TO_STDERR,
+               update_hook, refname, old_hex, new_hex, NULL);
        switch (code) {
        case 0:
                return 0;
@@ -187,7 +189,8 @@ static void run_update_post_hook(struct command *cmd)
                argc++;
        }
        argv[argc] = NULL;
-       run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
+       run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
+               | RUN_COMMAND_STDOUT_TO_STDERR);
 }
 
 /*
@@ -283,7 +286,7 @@ static const char *unpack(void)
                unpacker[0] = "unpack-objects";
                unpacker[1] = hdr_arg;
                unpacker[2] = NULL;
-               code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
+               code = run_command_v_opt(unpacker, RUN_GIT_CMD);
                switch (code) {
                case 0:
                        return NULL;
index af9f87418c6ed342e0a3d751b8f8e59fe5e8aeed..6e4ec463024a3e6cc4199ea1937f3b11e0a0dace 100644 (file)
@@ -1039,6 +1039,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                all_match = 1;
                                continue;
                        }
+                       if (!strncmp(arg, "--encoding=", 11)) {
+                               arg += 11;
+                               if (strcmp(arg, "none"))
+                                       git_log_output_encoding = strdup(arg);
+                               else
+                                       git_log_output_encoding = "";
+                               continue;
+                       }
 
                        opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
                        if (opts > 0) {
index 492ad3e64ce5d2435c029ab032f1221347f37c19..cfbad74d145145944352c568064cc2f8c0d4c5cb 100644 (file)
@@ -2,19 +2,20 @@
 #include "run-command.h"
 #include "exec_cmd.h"
 
-int run_command_v_opt(int argc, const char **argv, int flags)
+int run_command_v_opt(const char **argv, int flags)
 {
        pid_t pid = fork();
 
        if (pid < 0)
                return -ERR_RUN_COMMAND_FORK;
        if (!pid) {
-               if (flags & RUN_COMMAND_NO_STDIO) {
+               if (flags & RUN_COMMAND_NO_STDIN) {
                        int fd = open("/dev/null", O_RDWR);
                        dup2(fd, 0);
-                       dup2(fd, 1);
                        close(fd);
                }
+               if (flags & RUN_COMMAND_STDOUT_TO_STDERR)
+                       dup2(2, 1);
                if (flags & RUN_GIT_CMD) {
                        execv_git_cmd(argv);
                } else {
@@ -46,19 +47,17 @@ int run_command_v_opt(int argc, const char **argv, int flags)
        }
 }
 
-int run_command_v(int argc, const char **argv)
+int run_command_v(const char **argv)
 {
-       return run_command_v_opt(argc, argv, 0);
+       return run_command_v_opt(argv, 0);
 }
 
-int run_command(const char *cmd, ...)
+static int run_command_va_opt(int opt, const char *cmd, va_list param)
 {
        int argc;
        const char *argv[MAX_RUN_COMMAND_ARGS];
        const char *arg;
-       va_list param;
 
-       va_start(param, cmd);
        argv[0] = (char*) cmd;
        argc = 1;
        while (argc < MAX_RUN_COMMAND_ARGS) {
@@ -66,8 +65,29 @@ int run_command(const char *cmd, ...)
                if (!arg)
                        break;
        }
-       va_end(param);
        if (MAX_RUN_COMMAND_ARGS <= argc)
                return error("too many args to run %s", cmd);
-       return run_command_v_opt(argc, argv, 0);
+       return run_command_v_opt(argv, opt);
+}
+
+int run_command_opt(int opt, const char *cmd, ...)
+{
+       va_list params;
+       int r;
+
+       va_start(params, cmd);
+       r = run_command_va_opt(opt, cmd, params);
+       va_end(params);
+       return r;
+}
+
+int run_command(const char *cmd, ...)
+{
+       va_list params;
+       int r;
+
+       va_start(params, cmd);
+       r = run_command_va_opt(0, cmd, params);
+       va_end(params);
+       return r;
 }
index 70b477a7483ce3a4997b20ee02223eeb483bde6c..59c4476ced789441eea3f68bfc7377e7e15e9b14 100644 (file)
@@ -11,10 +11,12 @@ enum {
        ERR_RUN_COMMAND_WAITPID_NOEXIT,
 };
 
-#define RUN_COMMAND_NO_STDIO 1
+#define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
-int run_command_v_opt(int argc, const char **argv, int opt);
-int run_command_v(int argc, const char **argv);
+#define RUN_COMMAND_STDOUT_TO_STDERR 4
+int run_command_v_opt(const char **argv, int opt);
+int run_command_v(const char **argv);
+int run_command_opt(int opt, const char *cmd, ...);
 int run_command(const char *cmd, ...);
 
 #endif
diff --git a/setup.c b/setup.c
index 2afdba414a073705440f887593a1b5daa1023758..2ae57f7c94e304ef3468a27cd245c314a08046ed 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -131,28 +131,46 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
 }
 
 /*
- * Test if it looks like we're at the top level git directory.
+ * Test if it looks like we're at a git directory.
  * We want to see:
  *
- *  - either a .git/objects/ directory _or_ the proper
+ *  - either a objects/ directory _or_ the proper
  *    GIT_OBJECT_DIRECTORY environment variable
- *  - a refs/ directory under ".git"
+ *  - a refs/ directory
  *  - either a HEAD symlink or a HEAD file that is formatted as
  *    a proper "ref:".
  */
-static int is_toplevel_directory(void)
+static int is_git_directory(const char *suspect)
 {
-       if (access(".git/refs/", X_OK) ||
-           access(getenv(DB_ENVIRONMENT) ?
-                  getenv(DB_ENVIRONMENT) : ".git/objects/", X_OK) ||
-           validate_symref(".git/HEAD"))
+       char path[PATH_MAX];
+       size_t len = strlen(suspect);
+
+       strcpy(path, suspect);
+       if (getenv(DB_ENVIRONMENT)) {
+               if (access(getenv(DB_ENVIRONMENT), X_OK))
+                       return 0;
+       }
+       else {
+               strcpy(path + len, "/objects");
+               if (access(path, X_OK))
+                       return 0;
+       }
+
+       strcpy(path + len, "/refs");
+       if (access(path, X_OK))
                return 0;
+
+       strcpy(path + len, "/HEAD");
+       if (validate_symref(path))
+               return 0;
+
        return 1;
 }
 
 const char *setup_git_directory_gently(int *nongit_ok)
 {
        static char cwd[PATH_MAX+1];
+       const char *gitdirenv;
        int len, offset;
 
        /*
@@ -160,36 +178,17 @@ const char *setup_git_directory_gently(int *nongit_ok)
         * to do any discovery, but we still do repository
         * validation.
         */
-       if (getenv(GIT_DIR_ENVIRONMENT)) {
-               char path[PATH_MAX];
-               int len = strlen(getenv(GIT_DIR_ENVIRONMENT));
-               if (sizeof(path) - 40 < len)
+       gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
+       if (gitdirenv) {
+               if (PATH_MAX - 40 < strlen(gitdirenv))
                        die("'$%s' too big", GIT_DIR_ENVIRONMENT);
-               memcpy(path, getenv(GIT_DIR_ENVIRONMENT), len);
-               
-               strcpy(path + len, "/refs");
-               if (access(path, X_OK))
-                       goto bad_dir_environ;
-               strcpy(path + len, "/HEAD");
-               if (validate_symref(path))
-                       goto bad_dir_environ;
-               if (getenv(DB_ENVIRONMENT)) {
-                       if (access(getenv(DB_ENVIRONMENT), X_OK))
-                               goto bad_dir_environ;
-               }
-               else {
-                       strcpy(path + len, "/objects");
-                       if (access(path, X_OK))
-                               goto bad_dir_environ;
-               }
-               return NULL;
-       bad_dir_environ:
+               if (is_git_directory(gitdirenv))
+                       return NULL;
                if (nongit_ok) {
                        *nongit_ok = 1;
                        return NULL;
                }
-               path[len] = 0;
-               die("Not a git repository: '%s'", path);
+               die("Not a git repository: '%s'", gitdirenv);
        }
 
        if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
@@ -197,11 +196,17 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
        offset = len = strlen(cwd);
        for (;;) {
-               if (is_toplevel_directory())
+               if (is_git_directory(".git"))
                        break;
                chdir("..");
                do {
                        if (!offset) {
+                               if (is_git_directory(cwd)) {
+                                       if (chdir(cwd))
+                                               die("Cannot come back to cwd");
+                                       setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
+                                       return NULL;
+                               }
                                if (nongit_ok) {
                                        if (chdir(cwd))
                                                die("Cannot come back to cwd");
index e48a4ecdcf7129da1431928bdb942eae8c3e6515..a29caa06dc6545b7fc23b3446a713b75f49cd146 100755 (executable)
@@ -391,5 +391,15 @@ EOF
 
 test_expect_success "rename succeeded" "diff -u expect .git/config"
 
+test_expect_success numbers '
+
+       git-repo-config kilo.gram 1k &&
+       git-repo-config mega.ton 1m &&
+       k=$(git-repo-config --int --get kilo.gram) &&
+       test z1024 = "z$k" &&
+       m=$(git-repo-config --int --get mega.ton) &&
+       test z1048576 = "z$m"
+'
+
 test_done
 
index 46fd47cb0fedea8831d155d04651deb2b21d2e7c..6714b0dd6e6164eb17174465be536ee3a07d88e1 100755 (executable)
@@ -8,7 +8,7 @@ test_description='commit and log output encodings'
 . ./test-lib.sh
 
 compare_with () {
-       git-show -s "$1" | sed -e '1,/^$/d' -e 's/^    //' -e '$d' >current &&
+       git-show -s $1 | sed -e '1,/^$/d' -e 's/^    //' -e '$d' >current &&
        diff -u current "$2"
 }
 
@@ -112,4 +112,11 @@ do
        done
 done
 
+for H in ISO-8859-1 EUCJP ISO-2022-JP
+do
+       test_expect_success "No conversion with $H" '
+               compare_with "--encoding=none '$H'" ../t3900/'$H'.txt
+       '
+done
+
 test_done
diff --git a/utf8.c b/utf8.c
index 1eedd8b61aeed9867366df0b70ac849cdef985b9..7c80eeccb4537ab6d4387941c6262c89cab30d33 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -277,6 +277,15 @@ void print_wrapped_text(const char *text, int indent, int indent2, int width)
        }
 }
 
+int is_encoding_utf8(const char *name)
+{
+       if (!name)
+               return 1;
+       if (!strcasecmp(name, "utf-8") || !strcasecmp(name, "utf8"))
+               return 1;
+       return 0;
+}
+
 /*
  * Given a buffer and its encoding, return it re-encoded
  * with iconv.  If the conversion fails, returns NULL.
diff --git a/utf8.h b/utf8.h
index cae2a8e665c2cbe7bf31a49deed84250eaa37a33..a07c5a88af63d41ae963f230510a33d78b68a525 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -3,6 +3,8 @@
 
 int utf8_width(const char **start);
 int is_utf8(const char *text);
+int is_encoding_utf8(const char *name);
+
 void print_wrapped_text(const char *text, int indent, int indent2, int len);
 
 #ifndef NO_ICONV
index 294450b89916180ab603d566e7d3f281773a3b92..b83b3348cc3aab66b13cb565a0a0fabaef4b689b 100644 (file)
@@ -166,6 +166,8 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
                        size += xdl_recs_copy(xe2, m->i2 - m->i1 + i1,
                                        m->i1 + m->chg2 - i1, 0,
                                        dest ? dest + size : NULL);
+               else
+                       continue;
                i1 = m->i1 + m->chg1;
        }
        size += xdl_recs_copy(xe1, i1, xe1->xdf2.nrec - i1, 0,
@@ -213,9 +215,10 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
                        return -1;
                }
                if (!xscr) {
-                       /* If this happens, it's a bug. */
+                       /* If this happens, the changes are identical. */
                        xdl_free_env(&xe);
-                       return -2;
+                       m->mode = 4;
+                       continue;
                }
                x = xscr;
                m->i1 = xscr->i1 + i1;