Merge branch 'master' into sp/mmap

* 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.
This commit is contained in:
Junio C Hamano 2006-12-30 22:42:43 -08:00
Родитель 2c039da804 a862f97e98
Коммит 76d4e079ad
27 изменённых файлов: 321 добавлений и 84 удалений

Просмотреть файл

@ -82,13 +82,13 @@ core.logAllRefUpdates::
only when the file exists. If this configuration only when the file exists. If this configuration
variable is set to true, missing "$GIT_DIR/logs/<ref>" variable is set to true, missing "$GIT_DIR/logs/<ref>"
file is automatically created for branch heads. file is automatically created for branch heads.
+
This information can be used to determine what commit This information can be used to determine what commit
was the tip of a branch "2 days ago". was the tip of a branch "2 days ago".
+
This value is true by default in a repository that has This value is true by default in a repository that has
a working directory associated with it, and false by a working directory associated with it, and false by
default in a bare repository. default in a bare repository.
core.repositoryFormatVersion:: core.repositoryFormatVersion::
Internal variable identifying the repository format and layout Internal variable identifying the repository format and layout

Просмотреть файл

@ -81,6 +81,11 @@ Your parents must have hated you!::
Your sysadmin must hate you!:: Your sysadmin must hate you!::
The password(5) name field is longer than a giant static buffer. The password(5) name field is longer than a giant static buffer.
Discussion
----------
include::i18n.txt[]
See Also See Also
-------- --------
gitlink:git-write-tree[1] gitlink:git-write-tree[1]

Просмотреть файл

@ -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). refuses to run when given pathnames (but see `-i` option).
DISCUSSION
----------
include::i18n.txt[]
ENVIRONMENT VARIABLES ENVIRONMENT VARIABLES
--------------------- ---------------------
The command specified by either the VISUAL or EDITOR environment The command specified by either the VISUAL or EDITOR environment

Просмотреть файл

@ -31,7 +31,9 @@ include::pretty-formats.txt[]
Limits the number of commits to show. Limits the number of commits to show.
<since>..<until>:: <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:: -p::
Show the change the commit introduces in a patch form. 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 in the "release" branch, along with the list of paths
each commit modifies. each commit modifies.
Discussion
----------
include::i18n.txt[]
Author Author
------ ------
Written by Linus Torvalds <torvalds@osdl.org> Written by Linus Torvalds <torvalds@osdl.org>

Просмотреть файл

@ -87,7 +87,10 @@ OPTIONS
git-repo-config will ensure that the output is "true" or "false" git-repo-config will ensure that the output is "true" or "false"
--int:: --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 ENVIRONMENT

Просмотреть файл

@ -21,6 +21,7 @@ SYNOPSIS
[ \--stdin ] [ \--stdin ]
[ \--topo-order ] [ \--topo-order ]
[ \--parents ] [ \--parents ]
[ \--encoding[=<encoding>] ]
[ \--(author|committer|grep)=<pattern> ] [ \--(author|committer|grep)=<pattern> ]
[ [\--objects | \--objects-edge] [ \--unpacked ] ] [ [\--objects | \--objects-edge] [ \--unpacked ] ]
[ \--pretty | \--header ] [ \--pretty | \--header ]

Просмотреть файл

@ -30,8 +30,8 @@ This manual page describes only the most frequently used options.
OPTIONS OPTIONS
------- -------
<commitid>:: <object>::
ID of the commit to show. The name of the object to show.
include::pretty-formats.txt[] include::pretty-formats.txt[]
@ -40,7 +40,8 @@ EXAMPLES
-------- --------
git show v1.0.0:: 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}:: git show v1.0.0^{tree}::
Shows the tree pointed to by the tag `v1.0.0`. 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 Concatenates the contents of said Makefiles in the head
of the branch `master`. of the branch `master`.
Discussion
----------
include::i18n.txt[]
Author Author
------ ------
Written by Linus Torvalds <torvalds@osdl.org> and 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 Documentation

57
Documentation/i18n.txt Normal file
Просмотреть файл

@ -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.

Просмотреть файл

@ -76,3 +76,10 @@ displayed in full, regardless of whether --abbrev or
--no-abbrev are used, and 'parents' information show the --no-abbrev are used, and 'parents' information show the
true parent commits, without taking grafts nor history true parent commits, without taking grafts nor history
simplification into account. 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.

Просмотреть файл

@ -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 file in `$GIT_DIR/remotes` directory can be given; the
named file should be in the following format: named file should be in the following format:
URL: one of the above URL format ------------
Push: <refspec> URL: one of the above URL format
Pull: <refspec> Push: <refspec>
Pull: <refspec>
------------
Then such a short-hand is specified in place of Then such a short-hand is specified in place of
<repository> without <refspec> parameters on the command <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 Or, equivalently, in the `$GIT_DIR/config` (note the use
of `fetch` instead of `Pull:`): of `fetch` instead of `Pull:`):
------------
[remote "<remote>"] [remote "<remote>"]
url = <url> url = <url>
push = <refspec> push = <refspec>
fetch = <refspec> fetch = <refspec>
------------
The name of a file in `$GIT_DIR/branches` directory can be The name of a file in `$GIT_DIR/branches` directory can be
specified as an older notation short-hand; the named 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 without the fragment is equivalent to have this in the
corresponding file in the `$GIT_DIR/remotes/` directory. 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 while having `<url>#<head>` is equivalent to
URL: <url> ------------
Pull: refs/heads/<head>:<remote> URL: <url>
Pull: refs/heads/<head>:<remote>
------------

Просмотреть файл

@ -72,6 +72,9 @@ all:
# Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is # Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is
# generally faster on your platform than accessing the working directory. # 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_IPV6 if you lack IPv6 support and getaddrinfo().
# #
# Define NO_SOCKADDR_STORAGE if your platform does not have struct # Define NO_SOCKADDR_STORAGE if your platform does not have struct
@ -361,6 +364,7 @@ ifeq ($(uname_O),Cygwin)
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
NO_C99_FORMAT = YesPlease NO_C99_FORMAT = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
# There are conflicting reports about this. # There are conflicting reports about this.
# On some boxes NO_MMAP is needed, and not so elsewhere. # On some boxes NO_MMAP is needed, and not so elsewhere.
# Try commenting this out if you suspect MMAP is more efficient # Try commenting this out if you suspect MMAP is more efficient
@ -521,6 +525,9 @@ endif
ifdef NO_FAST_WORKING_DIRECTORY ifdef NO_FAST_WORKING_DIRECTORY
BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
endif endif
ifdef NO_TRUSTABLE_FILEMODE
BASIC_CFLAGS += -DNO_TRUSTABLE_FILEMODE
endif
ifdef NO_IPV6 ifdef NO_IPV6
BASIC_CFLAGS += -DNO_IPV6 BASIC_CFLAGS += -DNO_IPV6
endif endif

Просмотреть файл

@ -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 */ /* Not having i18n.commitencoding is the same as having utf-8 */
encoding_is_utf8 = (!git_commit_encoding || encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
!strcmp(git_commit_encoding, "utf-8"));
init_buffer(&buffer, &size); init_buffer(&buffer, &size);
add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1)); add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));

Просмотреть файл

@ -10,6 +10,12 @@
#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/" #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/"
#endif #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) static void safe_create_dir(const char *dir, int share)
{ {
if (mkdir(dir, 0777) < 0) { 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; struct stat st1;
char repo_version_string[10]; char repo_version_string[10];
int reinit; int reinit;
int filemode;
if (len > sizeof(path)-50) if (len > sizeof(path)-50)
die("insane git directory %s", git_dir); 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"); strcpy(path + len, "config");
/* Check filemode trustability */ /* Check filemode trustability */
if (!lstat(path, &st1)) { filemode = TEST_FILEMODE;
if (TEST_FILEMODE && !lstat(path, &st1)) {
struct stat st2; struct stat st2;
int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
!lstat(path, &st2) && !lstat(path, &st2) &&
st1.st_mode != st2.st_mode); 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 */ /* Enable logAllRefUpdates if a working tree is attached */
if (!is_bare_git_dir(git_dir)) if (!is_bare_git_dir(git_dir))

Просмотреть файл

@ -275,7 +275,7 @@ static int do_push(const char *repo)
argv[dest_argc] = NULL; argv[dest_argc] = NULL;
if (verbose) if (verbose)
fprintf(stderr, "Pushing to %s\n", dest); fprintf(stderr, "Pushing to %s\n", dest);
err = run_command_v(argc, argv); err = run_command_v(argv);
if (!err) if (!err)
continue; continue;
switch (err) { switch (err) {

Просмотреть файл

@ -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) static char *logmsg_reencode(const struct commit *commit)
{ {
char *encoding; char *encoding;
@ -633,6 +675,8 @@ static char *logmsg_reencode(const struct commit *commit)
: git_commit_encoding); : git_commit_encoding);
if (!output_encoding) if (!output_encoding)
output_encoding = "utf-8";
else if (!*output_encoding)
return NULL; return NULL;
encoding = get_header(commit, "encoding"); encoding = get_header(commit, "encoding");
if (!encoding || !strcmp(encoding, output_encoding)) { if (!encoding || !strcmp(encoding, output_encoding)) {
@ -640,6 +684,9 @@ static char *logmsg_reencode(const struct commit *commit)
return NULL; return NULL;
} }
out = reencode_string(commit->buffer, output_encoding, encoding); out = reencode_string(commit->buffer, output_encoding, encoding);
if (out)
out = replace_encoding_header(out, output_encoding);
free(encoding); free(encoding);
if (!out) if (!out)
return NULL; return NULL;

Просмотреть файл

@ -238,6 +238,12 @@ int git_config_int(const char *name, const char *value)
int val = strtol(value, &end, 0); int val = strtol(value, &end, 0);
if (!*end) if (!*end)
return val; 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); die("bad config value for '%s' in %s", name, config_file_name);
} }

8
git.c
Просмотреть файл

@ -63,14 +63,14 @@ static int handle_options(const char*** argv, int* argc)
fprintf(stderr, "No directory given for --git-dir.\n" ); fprintf(stderr, "No directory given for --git-dir.\n" );
usage(git_usage_string); usage(git_usage_string);
} }
setenv("GIT_DIR", (*argv)[1], 1); setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
(*argv)++; (*argv)++;
(*argc)--; (*argc)--;
} else if (!strncmp(cmd, "--git-dir=", 10)) { } 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")) { } else if (!strcmp(cmd, "--bare")) {
static char git_dir[1024]; static char git_dir[PATH_MAX+1];
setenv("GIT_DIR", getcwd(git_dir, 1024), 1); setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 1);
} else { } else {
fprintf(stderr, "Unknown option: %s\n", cmd); fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string); usage(git_usage_string);

Просмотреть файл

@ -73,7 +73,9 @@ static int run_update_hook(const char *refname,
if (access(update_hook, X_OK) < 0) if (access(update_hook, X_OK) < 0)
return 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) { switch (code) {
case 0: case 0:
return 0; return 0;
@ -187,7 +189,8 @@ static void run_update_post_hook(struct command *cmd)
argc++; argc++;
} }
argv[argc] = NULL; 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[0] = "unpack-objects";
unpacker[1] = hdr_arg; unpacker[1] = hdr_arg;
unpacker[2] = NULL; unpacker[2] = NULL;
code = run_command_v_opt(1, unpacker, RUN_GIT_CMD); code = run_command_v_opt(unpacker, RUN_GIT_CMD);
switch (code) { switch (code) {
case 0: case 0:
return NULL; return NULL;

Просмотреть файл

@ -1039,6 +1039,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
all_match = 1; all_match = 1;
continue; 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); opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) { if (opts > 0) {

Просмотреть файл

@ -2,19 +2,20 @@
#include "run-command.h" #include "run-command.h"
#include "exec_cmd.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(); pid_t pid = fork();
if (pid < 0) if (pid < 0)
return -ERR_RUN_COMMAND_FORK; return -ERR_RUN_COMMAND_FORK;
if (!pid) { if (!pid) {
if (flags & RUN_COMMAND_NO_STDIO) { if (flags & RUN_COMMAND_NO_STDIN) {
int fd = open("/dev/null", O_RDWR); int fd = open("/dev/null", O_RDWR);
dup2(fd, 0); dup2(fd, 0);
dup2(fd, 1);
close(fd); close(fd);
} }
if (flags & RUN_COMMAND_STDOUT_TO_STDERR)
dup2(2, 1);
if (flags & RUN_GIT_CMD) { if (flags & RUN_GIT_CMD) {
execv_git_cmd(argv); execv_git_cmd(argv);
} else { } 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; int argc;
const char *argv[MAX_RUN_COMMAND_ARGS]; const char *argv[MAX_RUN_COMMAND_ARGS];
const char *arg; const char *arg;
va_list param;
va_start(param, cmd);
argv[0] = (char*) cmd; argv[0] = (char*) cmd;
argc = 1; argc = 1;
while (argc < MAX_RUN_COMMAND_ARGS) { while (argc < MAX_RUN_COMMAND_ARGS) {
@ -66,8 +65,29 @@ int run_command(const char *cmd, ...)
if (!arg) if (!arg)
break; break;
} }
va_end(param);
if (MAX_RUN_COMMAND_ARGS <= argc) if (MAX_RUN_COMMAND_ARGS <= argc)
return error("too many args to run %s", cmd); 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;
} }

Просмотреть файл

@ -11,10 +11,12 @@ enum {
ERR_RUN_COMMAND_WAITPID_NOEXIT, 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 */ #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); #define RUN_COMMAND_STDOUT_TO_STDERR 4
int run_command_v(int argc, const char **argv); 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, ...); int run_command(const char *cmd, ...);
#endif #endif

73
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: * We want to see:
* *
* - either a .git/objects/ directory _or_ the proper * - either a objects/ directory _or_ the proper
* GIT_OBJECT_DIRECTORY environment variable * 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 * - either a HEAD symlink or a HEAD file that is formatted as
* a proper "ref:". * a proper "ref:".
*/ */
static int is_toplevel_directory(void) static int is_git_directory(const char *suspect)
{ {
if (access(".git/refs/", X_OK) || char path[PATH_MAX];
access(getenv(DB_ENVIRONMENT) ? size_t len = strlen(suspect);
getenv(DB_ENVIRONMENT) : ".git/objects/", X_OK) ||
validate_symref(".git/HEAD")) 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; return 0;
strcpy(path + len, "/HEAD");
if (validate_symref(path))
return 0;
return 1; return 1;
} }
const char *setup_git_directory_gently(int *nongit_ok) const char *setup_git_directory_gently(int *nongit_ok)
{ {
static char cwd[PATH_MAX+1]; static char cwd[PATH_MAX+1];
const char *gitdirenv;
int len, offset; 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 * to do any discovery, but we still do repository
* validation. * validation.
*/ */
if (getenv(GIT_DIR_ENVIRONMENT)) { gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
char path[PATH_MAX]; if (gitdirenv) {
int len = strlen(getenv(GIT_DIR_ENVIRONMENT)); if (PATH_MAX - 40 < strlen(gitdirenv))
if (sizeof(path) - 40 < len)
die("'$%s' too big", GIT_DIR_ENVIRONMENT); die("'$%s' too big", GIT_DIR_ENVIRONMENT);
memcpy(path, getenv(GIT_DIR_ENVIRONMENT), len); if (is_git_directory(gitdirenv))
return NULL;
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 (nongit_ok) { if (nongit_ok) {
*nongit_ok = 1; *nongit_ok = 1;
return NULL; return NULL;
} }
path[len] = 0; die("Not a git repository: '%s'", gitdirenv);
die("Not a git repository: '%s'", path);
} }
if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/') if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
@ -197,11 +196,17 @@ const char *setup_git_directory_gently(int *nongit_ok)
offset = len = strlen(cwd); offset = len = strlen(cwd);
for (;;) { for (;;) {
if (is_toplevel_directory()) if (is_git_directory(".git"))
break; break;
chdir(".."); chdir("..");
do { do {
if (!offset) { 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 (nongit_ok) {
if (chdir(cwd)) if (chdir(cwd))
die("Cannot come back to cwd"); die("Cannot come back to cwd");

Просмотреть файл

@ -391,5 +391,15 @@ EOF
test_expect_success "rename succeeded" "diff -u expect .git/config" 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 test_done

Просмотреть файл

@ -8,7 +8,7 @@ test_description='commit and log output encodings'
. ./test-lib.sh . ./test-lib.sh
compare_with () { 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" diff -u current "$2"
} }
@ -112,4 +112,11 @@ do
done done
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 test_done

9
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 * Given a buffer and its encoding, return it re-encoded
* with iconv. If the conversion fails, returns NULL. * with iconv. If the conversion fails, returns NULL.

2
utf8.h
Просмотреть файл

@ -3,6 +3,8 @@
int utf8_width(const char **start); int utf8_width(const char **start);
int is_utf8(const char *text); 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); void print_wrapped_text(const char *text, int indent, int indent2, int len);
#ifndef NO_ICONV #ifndef NO_ICONV

Просмотреть файл

@ -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, size += xdl_recs_copy(xe2, m->i2 - m->i1 + i1,
m->i1 + m->chg2 - i1, 0, m->i1 + m->chg2 - i1, 0,
dest ? dest + size : NULL); dest ? dest + size : NULL);
else
continue;
i1 = m->i1 + m->chg1; i1 = m->i1 + m->chg1;
} }
size += xdl_recs_copy(xe1, i1, xe1->xdf2.nrec - i1, 0, 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; return -1;
} }
if (!xscr) { if (!xscr) {
/* If this happens, it's a bug. */ /* If this happens, the changes are identical. */
xdl_free_env(&xe); xdl_free_env(&xe);
return -2; m->mode = 4;
continue;
} }
x = xscr; x = xscr;
m->i1 = xscr->i1 + i1; m->i1 = xscr->i1 + i1;