summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt14
-rw-r--r--Documentation/git-commit-tree.txt5
-rw-r--r--Documentation/git-commit.txt5
-rw-r--r--Documentation/git-log.txt10
-rw-r--r--Documentation/git-repo-config.txt5
-rw-r--r--Documentation/git-rev-list.txt1
-rw-r--r--Documentation/git-show.txt15
-rw-r--r--Documentation/i18n.txt57
-rw-r--r--Documentation/pretty-formats.txt7
-rw-r--r--Documentation/urls.txt23
-rw-r--r--Makefile7
-rw-r--r--builtin-commit-tree.c3
-rw-r--r--builtin-init-db.c15
-rw-r--r--builtin-push.c2
-rw-r--r--commit.c47
-rw-r--r--config.c6
-rw-r--r--git.c8
-rw-r--r--receive-pack.c9
-rw-r--r--revision.c8
-rw-r--r--run-command.c40
-rw-r--r--run-command.h8
-rw-r--r--setup.c73
-rwxr-xr-xt/t1300-repo-config.sh10
-rwxr-xr-xt/t3900-i18n-commit.sh9
-rw-r--r--utf8.c9
-rw-r--r--utf8.h2
-rw-r--r--xdiff/xmerge.c7
27 files changed, 321 insertions, 84 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d71653dc65..744484b982 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -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
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 41d1a1c4b3..77ba96ed8a 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -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]
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 0b74cd708e..a7adf24fa5 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -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
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 79643ac928..e9f746bbd4 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -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>
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
index b379ec5075..c55a8ba0dc 100644
--- a/Documentation/git-repo-config.txt
+++ b/Documentation/git-repo-config.txt
@@ -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
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 9e0dcf8d3f..86c94e7dfd 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -21,6 +21,7 @@ SYNOPSIS
[ \--stdin ]
[ \--topo-order ]
[ \--parents ]
+ [ \--encoding[=<encoding>] ]
[ \--(author|committer|grep)=<pattern> ]
[ [\--objects | \--objects-edge] [ \--unpacked ] ]
[ \--pretty | \--header ]
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index 98dea6125d..c210b9af6b 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -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
index 0000000000..b4cbb3830e
--- /dev/null
+++ b/Documentation/i18n.txt
@@ -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.
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 996f628903..fb0b0b9582 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -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.
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index 670827c323..870c95073b 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -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>
+------------
diff --git a/Makefile b/Makefile
index 93dc4948d3..fa1a02289c 100644
--- 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
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index 146aaffd28..0651e5927e 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -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));
diff --git a/builtin-init-db.c b/builtin-init-db.c
index 01f366ad0b..97fd82ff06 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -10,6 +10,12 @@
#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))
diff --git a/builtin-push.c b/builtin-push.c
index b7412e8293..7a3d2bb064 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -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) {
diff --git a/commit.c b/commit.c
index eb06afbbe0..afdf27eece 100644
--- 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;
diff --git a/config.c b/config.c
index 2e0d5a8681..5cbd130be2 100644
--- 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 50ebd869ad..c82ca458e4 100644
--- 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);
diff --git a/receive-pack.c b/receive-pack.c
index 59b682c03a..c176d8fd00 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -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;
diff --git a/revision.c b/revision.c
index af9f87418c..6e4ec46302 100644
--- a/revision.c
+++ b/revision.c
@@ -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) {
diff --git a/run-command.c b/run-command.c
index 492ad3e64c..cfbad74d14 100644
--- a/run-command.c
+++ b/run-command.c
@@ -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;
}
diff --git a/run-command.h b/run-command.h
index 70b477a748..59c4476ced 100644
--- a/run-command.h
+++ b/run-command.h
@@ -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 2afdba414a..2ae57f7c94 100644
--- 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");
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index e48a4ecdcf..a29caa06dc 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -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
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 46fd47cb0f..6714b0dd6e 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -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 1eedd8b61a..7c80eeccb4 100644
--- 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 cae2a8e665..a07c5a88af 100644
--- 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
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 294450b899..b83b3348cc 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -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;