summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.5.1.txt2
-rwxr-xr-xDocumentation/build-docdep.perl6
-rw-r--r--Documentation/config.txt5
-rw-r--r--Documentation/git-add.txt2
-rw-r--r--Documentation/git-branch.txt6
-rw-r--r--Documentation/git-bundle.txt8
-rw-r--r--Documentation/git-quiltimport.txt8
-rw-r--r--Documentation/git-send-email.txt12
-rw-r--r--Documentation/git-svn.txt121
-rw-r--r--Documentation/pretty-formats.txt44
-rw-r--r--Makefile10
-rw-r--r--builtin-archive.c2
-rw-r--r--builtin-branch.c12
-rw-r--r--cache.h3
-rw-r--r--commit.c195
-rw-r--r--commit.h1
-rw-r--r--date.c20
-rw-r--r--git-compat-util.h6
-rwxr-xr-xgit-gc.sh2
-rwxr-xr-xgit-merge.sh2
-rw-r--r--git.c2
-rw-r--r--http-push.c10
-rw-r--r--log-tree.c2
-rw-r--r--refs.c2
-rw-r--r--templates/hooks--update11
-rw-r--r--utf8.c39
-rw-r--r--utf8.h2
27 files changed, 419 insertions, 116 deletions
diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt
index 5ce385b442..aa371be1da 100644
--- a/Documentation/RelNotes-1.5.1.txt
+++ b/Documentation/RelNotes-1.5.1.txt
@@ -50,7 +50,7 @@ Updates since v1.5.0
LF at the end of lines. Currently, which paths to consider
'text' (i.e. be subjected to the autocrlf mechanism) is
decided purely based on the contents, but the plan is to
- allow users to explicitly override this heuristics based on
+ allow users to explicitly override this heuristic based on
paths.
- The behaviour of 'git-apply', when run in a subdirectory,
diff --git a/Documentation/build-docdep.perl b/Documentation/build-docdep.perl
index 489389c32a..ba4205e030 100755
--- a/Documentation/build-docdep.perl
+++ b/Documentation/build-docdep.perl
@@ -41,10 +41,6 @@ while ($changed) {
while (my ($text, $included) = each %include) {
if (! exists $included{$text} &&
(my $base = $text) =~ s/\.txt$//) {
- my ($suffix) = '1';
- if ($base eq 'git') {
- $suffix = '7'; # yuck...
- }
- print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n";
+ print "$base.html $base.xml : ", join(" ", keys %$included), "\n";
}
}
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d2b4a05ca5..d20902bc33 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -341,6 +341,11 @@ format.headers::
Additional email headers to include in a patch to be submitted
by mail. See gitlink:git-format-patch[1].
+format.suffix::
+ The default for format-patch is to output files with the suffix
+ `.patch`. Use this variable to change that suffix (make sure to
+ include the dot if you want it).
+
gc.packrefs::
`git gc` does not run `git pack-refs` in a bare repository by
default so that older dumb-transport clients can still fetch
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index b73a99d61f..755d7186f5 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -52,7 +52,7 @@ OPTIONS
-f::
Allow adding otherwise ignored files.
-\i, \--interactive::
+-i, \--interactive::
Add modified contents in the working tree interactively to
the index.
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index aa1fdd402a..3ea3b80635 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -8,7 +8,8 @@ git-branch - List, create, or delete branches
SYNOPSIS
--------
[verse]
-'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
+'git-branch' [--color | --no-color] [-r | -a]
+ [-v [--abbrev=<length> | --no-abbrev]]
'git-branch' [-l] [-f] <branchname> [<start-point>]
'git-branch' (-m | -M) [<oldbranch>] <newbranch>
'git-branch' (-d | -D) [-r] <branchname>...
@@ -80,6 +81,9 @@ OPTIONS
Alter minimum display length for sha1 in output listing,
default value is 7.
+--no-abbrev::
+ Display the full sha1s in output listing rather than abbreviating them.
+
<branchname>::
The name of the branch to create or delete.
The new branch name must pass all checks defined by
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 4ea9e85d5e..92e7a68722 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -19,7 +19,7 @@ DESCRIPTION
Some workflows require that one or more branches of development on one
machine be replicated on another machine, but the two machines cannot
be directly connected so the interactive git protocols (git, ssh,
-rsync, http) cannot be used. This command provides suport for
+rsync, http) cannot be used. This command provides support for
git-fetch and git-pull to operate by packaging objects and references
in an archive at the originating machine, then importing those into
another repository using gitlink:git-fetch[1] and gitlink:git-pull[1]
@@ -58,7 +58,7 @@ unbundle <file>::
gitlink:git-fetch[1].
[git-rev-list-args...]::
- A list of arguments, accepatble to git-rev-parse and
+ A list of arguments, acceptable to git-rev-parse and
git-rev-list, that specify the specific objects and references
to transport. For example, "master~10..master" causes the
current master reference to be packaged along with all objects
@@ -70,7 +70,7 @@ unbundle <file>::
[refname...]::
A list of references used to limit the references reported as
available. This is principally of use to git-fetch, which
- expects to recieve only those references asked for and not
+ expects to receive only those references asked for and not
necessarily everything in the pack (in this case, git-bundle is
acting like gitlink:git-fetch-pack[1]).
@@ -87,7 +87,7 @@ specified explicitly (e.g., ^master~10), or implicitly (e.g.,
master~10..master, master --since=10.days.ago).
It is very important that the basis used be held by the destination.
-It is ok to err on the side of conservatism, causing the bundle file
+It is okay to err on the side of conservatism, causing the bundle file
to contain objects already in the destination as these are ignored
when unpacking at the destination.
diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt
index 6e9a8c369a..296937a416 100644
--- a/Documentation/git-quiltimport.txt
+++ b/Documentation/git-quiltimport.txt
@@ -42,10 +42,10 @@ OPTIONS
--patches <dir>::
The directory to find the quilt patches and the
quilt series file.
-
- The default for the patch directory is patches
- or the value of the $QUILT_PATCHES environment
- variable.
++
+The default for the patch directory is patches
+or the value of the $QUILT_PATCHES environment
+variable.
Author
------
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 4c8d907bd5..35b0104e4a 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -26,13 +26,13 @@ The options available are:
--bcc::
Specify a "Bcc:" value for each email.
-
- The --bcc option must be repeated for each user you want on the bcc list.
++
+The --bcc option must be repeated for each user you want on the bcc list.
--cc::
Specify a starting "Cc:" value for each email.
-
- The --cc option must be repeated for each user you want on the cc list.
++
+The --cc option must be repeated for each user you want on the cc list.
--chain-reply-to, --no-chain-reply-to::
If this is set, each email will be sent as a reply to the previous
@@ -87,8 +87,8 @@ The options available are:
Specify the primary recipient of the emails generated.
Generally, this will be the upstream maintainer of the
project involved.
-
- The --to option must be repeated for each user you want on the to list.
++
+The --to option must be repeated for each user you want on the to list.
Author
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index cf094ca357..9b5a3d6196 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -63,7 +63,7 @@ COMMANDS
transports (eg svn+ssh://), you must include the username in
the URL, eg svn+ssh://foo@svn.bar.com/project
---prefix=<prefix>
+--prefix=<prefix>::
This allows one to specify a prefix which is prepended
to the names of remotes if trunk/branches/tags are
specified. The prefix does not automatically include a
@@ -94,16 +94,16 @@ COMMANDS
This fetches revisions from the SVN parent of the current HEAD
and rebases the current (uncommitted to SVN) work against it.
- This works similarly to 'svn update' or 'git-pull' except that
- it preserves linear history with 'git-rebase' instead of
- 'git-merge' for ease of dcommit-ing with git-svn.
+This works similarly to 'svn update' or 'git-pull' except that
+it preserves linear history with 'git-rebase' instead of
+'git-merge' for ease of dcommit-ing with git-svn.
- This accepts all options that 'git-svn fetch' and 'git-rebase'
- accepts. However '--fetch-all' only fetches from the current
- [svn-remote], and not all [svn-remote] definitions.
+This accepts all options that 'git-svn fetch' and 'git-rebase'
+accepts. However '--fetch-all' only fetches from the current
+[svn-remote], and not all [svn-remote] definitions.
- Like 'git-rebase'; this requires that the working tree be clean
- and have no uncommitted changes.
+Like 'git-rebase'; this requires that the working tree be clean
+and have no uncommitted changes.
'dcommit'::
Commit each diff from a specified head directly to the SVN
@@ -117,29 +117,40 @@ COMMANDS
alternative to HEAD.
This is advantageous over 'set-tree' (below) because it produces
cleaner, more linear history.
+--
'log'::
This should make it easy to look up svn log messages when svn
users refer to -r/--revision numbers.
++
+The following features from `svn log' are supported:
++
+--
+--revision=<n>[:<n>];;
+ is supported, non-numeric args are not:
+ HEAD, NEXT, BASE, PREV, etc ...
+-v/--verbose;;
+ it's not completely compatible with the --verbose
+ output in svn log, but reasonably close.
+--limit=<n>;;
+ is NOT the same as --max-count, doesn't count
+ merged/excluded commits
+--incremental;;
+ supported
+--
++
+New features:
++
+--
+--show-commit;;
+ shows the git commit sha1, as well
+--oneline;;
+ our version of --pretty=oneline
+--
++
+Any other arguments are passed directly to `git log'
- The following features from `svn log' are supported:
-
- --revision=<n>[:<n>] - is supported, non-numeric args are not:
- HEAD, NEXT, BASE, PREV, etc ...
- -v/--verbose - it's not completely compatible with
- the --verbose output in svn log, but
- reasonably close.
- --limit=<n> - is NOT the same as --max-count,
- doesn't count merged/excluded commits
- --incremental - supported
-
- New features:
-
- --show-commit - shows the git commit sha1, as well
- --oneline - our version of --pretty=oneline
-
- Any other arguments are passed directly to `git log'
-
+--
'set-tree'::
You should consider using 'dcommit' instead of this command.
Commit specified commit or tree objects to SVN. This relies on
@@ -256,16 +267,18 @@ config key: svn.authorsfile
Make git-svn less verbose.
--repack[=<n>]::
---repack-flags=<flags>
- These should help keep disk usage sane for large fetches
- with many revisions.
+--repack-flags=<flags>::
+
+These should help keep disk usage sane for large fetches
+with many revisions.
- --repack takes an optional argument for the number of revisions
- to fetch before repacking. This defaults to repacking every
- 1000 commits fetched if no argument is specified.
+--repack takes an optional argument for the number of revisions
+to fetch before repacking. This defaults to repacking every
+1000 commits fetched if no argument is specified.
- --repack-flags are passed directly to gitlink:git-repack[1].
+--repack-flags are passed directly to gitlink:git-repack[1].
+[verse]
config key: svn.repack
config key: svn.repackflags
@@ -323,28 +336,30 @@ CONFIG FILE-ONLY OPTIONS
svn.noMetadata::
svn-remote.<name>.noMetadata::
- This gets rid of the git-svn-id: lines at the end of every commit.
- If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
- be able to rebuild it and you won't be able to fetch again,
- either. This is fine for one-shot imports.
+This gets rid of the git-svn-id: lines at the end of every commit.
+
+If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
+be able to rebuild it and you won't be able to fetch again,
+either. This is fine for one-shot imports.
- The 'git-svn log' command will not work on repositories using
- this, either. Using this conflicts with the 'useSvmProps'
- option for (hopefully) obvious reasons.
+The 'git-svn log' command will not work on repositories using
+this, either. Using this conflicts with the 'useSvmProps'
+option for (hopefully) obvious reasons.
svn.useSvmProps::
svn-remote.<name>.useSvmProps::
- This allows git-svn to re-map repository URLs and UUIDs from
- mirrors created using SVN::Mirror (or svk) for metadata.
- If an SVN revision has a property, "svm:headrev", it is likely
- that the revision was created by SVN::Mirror (also used by SVK).
- The property contains a repository UUID and a revision. We want
- to make it look like we are mirroring the original URL, so
- introduce a helper function that returns the original identity
- URL and UUID, and use it when generating metadata in commit
- messages.
+This allows git-svn to re-map repository URLs and UUIDs from
+mirrors created using SVN::Mirror (or svk) for metadata.
+
+If an SVN revision has a property, "svm:headrev", it is likely
+that the revision was created by SVN::Mirror (also used by SVK).
+The property contains a repository UUID and a revision. We want
+to make it look like we are mirroring the original URL, so
+introduce a helper function that returns the original identity
+URL and UUID, and use it when generating metadata in commit
+messages.
svn.useSvnsyncProps::
svn-remote.<name>.useSvnsyncprops::
@@ -369,8 +384,8 @@ section because they affect the 'git-svn-id:' metadata line.
--
-Basic Examples
-~~~~~~~~~~~~~~
+BASIC EXAMPLES
+--------------
Tracking and contributing to a the trunk of a Subversion-managed project:
@@ -405,7 +420,7 @@ Tracking and contributing to an entire Subversion-managed project
# with the appropriate name):
git reset --hard remotes/trunk
# You may only dcommit to one branch/tag/trunk at a time. The usage
-# of dcommit/rebase/show-ignore should be teh same as above.
+# of dcommit/rebase/show-ignore should be the same as above.
------------------------------------------------------------------------
REBASE VS. PULL/MERGE
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index fb0b0b9582..2fe6c31967 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -77,9 +77,53 @@ displayed in full, regardless of whether --abbrev or
true parent commits, without taking grafts nor history
simplification into account.
+ * 'format:'
++
+The 'format:' format allows you to specify which information
+you want to show. It works a little bit like printf format,
+with the notable exception that you get a newline with '%n'
+instead of '\n'.
+
+E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<"'
+would show something like this:
+
+The author of fe6e0ee was Junio C Hamano, 23 hours ago
+The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
+
+The placeholders are:
+
+- '%H': commit hash
+- '%h': abbreviated commit hash
+- '%T': tree hash
+- '%t': abbreviated tree hash
+- '%P': parent hashes
+- '%p': abbreviated parent hashes
+- '%an': author name
+- '%ae': author email
+- '%ad': author date
+- '%aD': author date, RFC2822 style
+- '%ar': author date, relative
+- '%at': author date, UNIX timestamp
+- '%cn': committer name
+- '%ce': committer email
+- '%cd': committer date
+- '%cD': committer date, RFC2822 style
+- '%cr': committer date, relative
+- '%ct': committer date, UNIX timestamp
+- '%e': encoding
+- '%s': subject
+- '%b': body
+- '%Cred': switch color to red
+- '%Cgreen': switch color to green
+- '%Cblue': switch color to blue
+- '%Creset': reset color
+- '%n': newline
+
+
--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/Makefile b/Makefile
index 23ab7d6f9f..a221bdc027 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,9 @@ all::
#
# Define NO_ICONV if your libc does not properly support iconv.
#
+# Define OLD_ICONV if your library has an old iconv(), where the second
+# (input buffer pointer) parameter is declared with type (const char **).
+#
# Define NO_R_TO_GCC if your gcc does not like "-R/path/lib" that
# tells runtime paths to dynamic libraries; "-Wl,-rpath=/path/lib"
# is used instead.
@@ -378,7 +381,6 @@ ifeq ($(uname_O),Cygwin)
NO_STRCASESTR = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease
- NO_C99_FORMAT = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
# There are conflicting reports about this.
@@ -576,6 +578,10 @@ ifdef NO_ICONV
BASIC_CFLAGS += -DNO_ICONV
endif
+ifdef OLD_ICONV
+ BASIC_CFLAGS += -DOLD_ICONV
+endif
+
ifdef PPC_SHA1
SHA1_HEADER = "ppc/sha1.h"
LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
@@ -780,7 +786,7 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
-$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
+$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
$(DIFF_OBJS): diffcore.h
diff --git a/builtin-archive.c b/builtin-archive.c
index 8ea6cb1efc..2fae885f5c 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -252,8 +252,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
memset(&ar, 0, sizeof(ar));
tree_idx = parse_archive_args(argc, argv, &ar);
- if (prefix == NULL)
- prefix = setup_git_directory();
argv += tree_idx;
parse_treeish_arg(argv, &ar.args, prefix);
diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b00a2..d371849655 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
#include "builtin.h"
static const char builtin_branch_usage[] =
- "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
+ "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
#define REF_UNKNOWN_TYPE 0x00
#define REF_LOCAL_BRANCH 0x01
@@ -446,8 +446,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
reflog = 1;
continue;
}
+ if (!prefixcmp(arg, "--no-abbrev")) {
+ abbrev = 0;
+ continue;
+ }
if (!prefixcmp(arg, "--abbrev=")) {
- abbrev = atoi(arg+9);
+ abbrev = strtoul(arg + 9, NULL, 10);
+ if (abbrev < MINIMUM_ABBREV)
+ abbrev = MINIMUM_ABBREV;
+ else if (abbrev > 40)
+ abbrev = 40;
continue;
}
if (!strcmp(arg, "-v")) {
diff --git a/cache.h b/cache.h
index b84e3decfc..8018b2cd3b 100644
--- a/cache.h
+++ b/cache.h
@@ -327,7 +327,8 @@ extern void *read_object_with_reference(const unsigned char *sha1,
unsigned long *size,
unsigned char *sha1_ret);
-const char *show_date(unsigned long time, int timezone, int relative);
+enum date_mode { DATE_NORMAL = 0, DATE_RELATIVE, DATE_SHORT };
+const char *show_date(unsigned long time, int timezone, enum date_mode mode);
const char *show_rfc2822_date(unsigned long time, int timezone);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
diff --git a/commit.c b/commit.c
index da515a4973..5552527342 100644
--- a/commit.c
+++ b/commit.c
@@ -3,6 +3,7 @@
#include "commit.h"
#include "pkt-line.h"
#include "utf8.h"
+#include "interpolate.h"
int save_commit_buffer = 1;
@@ -36,8 +37,11 @@ struct cmt_fmt_map {
{ "full", 5, CMIT_FMT_FULL },
{ "fuller", 5, CMIT_FMT_FULLER },
{ "oneline", 1, CMIT_FMT_ONELINE },
+ { "format:", 7, CMIT_FMT_USERFORMAT},
};
+static char *user_format;
+
enum cmit_fmt get_commit_format(const char *arg)
{
int i;
@@ -46,6 +50,12 @@ enum cmit_fmt get_commit_format(const char *arg)
return CMIT_FMT_DEFAULT;
if (*arg == '=')
arg++;
+ if (!prefixcmp(arg, "format:")) {
+ if (user_format)
+ free(user_format);
+ user_format = xstrdup(arg + 7);
+ return CMIT_FMT_USERFORMAT;
+ }
for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) &&
!strncmp(arg, cmt_fmts[i].n, strlen(arg)))
@@ -710,6 +720,188 @@ static char *logmsg_reencode(const struct commit *commit,
return out;
}
+static char *xstrndup(const char *text, int len)
+{
+ char *result = xmalloc(len + 1);
+ memcpy(result, text, len);
+ result[len] = '\0';
+ return result;
+}
+
+static void fill_person(struct interp *table, const char *msg, int len)
+{
+ int start, end, tz = 0;
+ unsigned long date;
+ char *ep;
+
+ /* parse name */
+ for (end = 0; end < len && msg[end] != '<'; end++)
+ ; /* do nothing */
+ start = end + 1;
+ while (end > 0 && isspace(msg[end - 1]))
+ end--;
+ table[0].value = xstrndup(msg, end);
+
+ if (start >= len)
+ return;
+
+ /* parse email */
+ for (end = start + 1; end < len && msg[end] != '>'; end++)
+ ; /* do nothing */
+
+ if (end >= len)
+ return;
+
+ table[1].value = xstrndup(msg + start, end - start);
+
+ /* parse date */
+ for (start = end + 1; start < len && isspace(msg[start]); start++)
+ ; /* do nothing */
+ if (start >= len)
+ return;
+ date = strtoul(msg + start, &ep, 10);
+ if (msg + start == ep)
+ return;
+
+ table[5].value = xstrndup(msg + start, ep - msg + start);
+
+ /* parse tz */
+ for (start = ep - msg + 1; start < len && isspace(msg[start]); start++)
+ ; /* do nothing */
+ if (start + 1 < len) {
+ tz = strtoul(msg + start + 1, NULL, 10);
+ if (msg[start] == '-')
+ tz = -tz;
+ }
+
+ interp_set_entry(table, 2, show_date(date, tz, 0));
+ interp_set_entry(table, 3, show_rfc2822_date(date, tz));
+ interp_set_entry(table, 4, show_date(date, tz, 1));
+}
+
+static long format_commit_message(const struct commit *commit,
+ const char *msg, char *buf, unsigned long space)
+{
+ struct interp table[] = {
+ { "%H" }, /* commit hash */
+ { "%h" }, /* abbreviated commit hash */
+ { "%T" }, /* tree hash */
+ { "%t" }, /* abbreviated tree hash */
+ { "%P" }, /* parent hashes */
+ { "%p" }, /* abbreviated parent hashes */
+ { "%an" }, /* author name */
+ { "%ae" }, /* author email */
+ { "%ad" }, /* author date */
+ { "%aD" }, /* author date, RFC2822 style */
+ { "%ar" }, /* author date, relative */
+ { "%at" }, /* author date, UNIX timestamp */
+ { "%cn" }, /* committer name */
+ { "%ce" }, /* committer email */
+ { "%cd" }, /* committer date */
+ { "%cD" }, /* committer date, RFC2822 style */
+ { "%cr" }, /* committer date, relative */
+ { "%ct" }, /* committer date, UNIX timestamp */
+ { "%e" }, /* encoding */
+ { "%s" }, /* subject */
+ { "%b" }, /* body */
+ { "%Cred" }, /* red */
+ { "%Cgreen" }, /* green */
+ { "%Cblue" }, /* blue */
+ { "%Creset" }, /* reset color */
+ { "%n" } /* newline */
+ };
+ enum interp_index {
+ IHASH = 0, IHASH_ABBREV,
+ ITREE, ITREE_ABBREV,
+ IPARENTS, IPARENTS_ABBREV,
+ IAUTHOR_NAME, IAUTHOR_EMAIL,
+ IAUTHOR_DATE, IAUTHOR_DATE_RFC2822, IAUTHOR_DATE_RELATIVE,
+ IAUTHOR_TIMESTAMP,
+ ICOMMITTER_NAME, ICOMMITTER_EMAIL,
+ ICOMMITTER_DATE, ICOMMITTER_DATE_RFC2822,
+ ICOMMITTER_DATE_RELATIVE, ICOMMITTER_TIMESTAMP,
+ IENCODING,
+ ISUBJECT,
+ IBODY,
+ IRED, IGREEN, IBLUE, IRESET_COLOR,
+ INEWLINE
+ };
+ struct commit_list *p;
+ char parents[1024];
+ int i;
+ enum { HEADER, SUBJECT, BODY } state;
+
+ if (INEWLINE + 1 != ARRAY_SIZE(table))
+ die("invalid interp table!");
+
+ /* these are independent of the commit */
+ interp_set_entry(table, IRED, "\033[31m");
+ interp_set_entry(table, IGREEN, "\033[32m");
+ interp_set_entry(table, IBLUE, "\033[34m");
+ interp_set_entry(table, IRESET_COLOR, "\033[m");
+ interp_set_entry(table, INEWLINE, "\n");
+
+ /* these depend on the commit */
+ if (!commit->object.parsed)
+ parse_object(commit->object.sha1);
+ interp_set_entry(table, IHASH, sha1_to_hex(commit->object.sha1));
+ interp_set_entry(table, IHASH_ABBREV,
+ find_unique_abbrev(commit->object.sha1,
+ DEFAULT_ABBREV));
+ interp_set_entry(table, ITREE, sha1_to_hex(commit->tree->object.sha1));
+ interp_set_entry(table, ITREE_ABBREV,
+ find_unique_abbrev(commit->tree->object.sha1,
+ DEFAULT_ABBREV));
+ for (i = 0, p = commit->parents;
+ p && i < sizeof(parents) - 1;
+ p = p->next)
+ i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ",
+ sha1_to_hex(p->item->object.sha1));
+ interp_set_entry(table, IPARENTS, parents);
+ for (i = 0, p = commit->parents;
+ p && i < sizeof(parents) - 1;
+ p = p->next)
+ i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ",
+ find_unique_abbrev(p->item->object.sha1,
+ DEFAULT_ABBREV));
+ interp_set_entry(table, IPARENTS_ABBREV, parents);
+
+ for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
+ int eol;
+ for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
+ ; /* do nothing */
+
+ if (state == SUBJECT) {
+ table[ISUBJECT].value = xstrndup(msg + i, eol - i);
+ i = eol;
+ }
+ if (i == eol) {
+ state++;
+ /* strip empty lines */
+ while (msg[eol + 1] == '\n')
+ eol++;
+ } else if (!prefixcmp(msg + i, "author "))
+ fill_person(table + IAUTHOR_NAME,
+ msg + i + 7, eol - i - 7);
+ else if (!prefixcmp(msg + i, "committer "))
+ fill_person(table + ICOMMITTER_NAME,
+ msg + i + 10, eol - i - 10);
+ else if (!prefixcmp(msg + i, "encoding "))
+ table[IENCODING].value = xstrndup(msg + i, eol - i);
+ i = eol;
+ }
+ if (msg[i])
+ table[IBODY].value = xstrdup(msg + i);
+ for (i = 0; i < ARRAY_SIZE(table); i++)
+ if (!table[i].value)
+ interp_set_entry(table, i, "<unknown>");
+
+ interpolate(buf, space, user_format, table, ARRAY_SIZE(table));
+ interp_clear_table(table, ARRAY_SIZE(table));
+
+ return strlen(buf);
+}
+
unsigned long pretty_print_commit(enum cmit_fmt fmt,
const struct commit *commit,
unsigned long len,
@@ -727,6 +919,9 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
char *reencoded;
char *encoding;
+ if (fmt == CMIT_FMT_USERFORMAT)
+ return format_commit_message(commit, msg, buf, space);
+
encoding = (git_log_output_encoding
? git_log_output_encoding
: git_commit_encoding);
diff --git a/commit.h b/commit.h
index c73744463c..83507a07e4 100644
--- a/commit.h
+++ b/commit.h
@@ -47,6 +47,7 @@ enum cmit_fmt {
CMIT_FMT_FULLER,
CMIT_FMT_ONELINE,
CMIT_FMT_EMAIL,
+ CMIT_FMT_USERFORMAT,
CMIT_FMT_UNSPECIFIED,
};
diff --git a/date.c b/date.c
index 542c004c2e..0ceccbe034 100644
--- a/date.c
+++ b/date.c
@@ -55,12 +55,12 @@ static struct tm *time_to_tm(unsigned long time, int tz)
return gmtime(&t);
}
-const char *show_date(unsigned long time, int tz, int relative)
+const char *show_date(unsigned long time, int tz, enum date_mode mode)
{
struct tm *tm;
static char timebuf[200];
- if (relative) {
+ if (mode == DATE_RELATIVE) {
unsigned long diff;
struct timeval now;
gettimeofday(&now, NULL);
@@ -105,12 +105,16 @@ const char *show_date(unsigned long time, int tz, int relative)
tm = time_to_tm(time, tz);
if (!tm)
return NULL;
- sprintf(timebuf, "%.3s %.3s %d %02d:%02d:%02d %d %+05d",
- weekday_names[tm->tm_wday],
- month_names[tm->tm_mon],
- tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- tm->tm_year + 1900, tz);
+ if (mode == DATE_SHORT)
+ sprintf(timebuf, "%04d-%02d-%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday);
+ else
+ sprintf(timebuf, "%.3s %.3s %d %02d:%02d:%02d %d %+05d",
+ weekday_names[tm->tm_wday],
+ month_names[tm->tm_mon],
+ tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ tm->tm_year + 1900, tz);
return timebuf;
}
diff --git a/git-compat-util.h b/git-compat-util.h
index 5d154faef6..56212b2f11 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -49,9 +49,15 @@
#include <netdb.h>
#include <pwd.h>
#include <inttypes.h>
+#if defined(__CYGWIN__)
+#undef _XOPEN_SOURCE
+#include <grp.h>
+#define _XOPEN_SOURCE 600
+#else
#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
#include <grp.h>
#define _ALL_SOURCE 1
+#endif
#ifndef NO_ICONV
#include <iconv.h>
diff --git a/git-gc.sh b/git-gc.sh
index 1a45de5dff..436d7caff5 100755
--- a/git-gc.sh
+++ b/git-gc.sh
@@ -4,7 +4,7 @@
#
# Cleanup unreachable files and optimize the repository.
-USAGE='git-gc [--prune]'
+USAGE='[--prune]'
SUBDIRECTORY_OK=Yes
. git-sh-setup
diff --git a/git-merge.sh b/git-merge.sh
index 498c938c45..4afcd95316 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -294,7 +294,7 @@ f,*)
git-update-index --refresh 2>/dev/null
new_head=$(git-rev-parse --verify "$1^0") &&
git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
- finish "$new_head" "Fast forward"
+ finish "$new_head" "Fast forward" || exit
dropsave
exit 0
;;
diff --git a/git.c b/git.c
index 9b37f42321..04fc99a3dd 100644
--- a/git.c
+++ b/git.c
@@ -226,7 +226,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
{ "annotate", cmd_annotate, USE_PAGER },
{ "apply", cmd_apply },
- { "archive", cmd_archive },
+ { "archive", cmd_archive, RUN_SETUP },
{ "blame", cmd_blame, RUN_SETUP },
{ "branch", cmd_branch, RUN_SETUP },
{ "bundle", cmd_bundle },
diff --git a/http-push.c b/http-push.c
index 68b78b538a..cbb02d3bc1 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1271,7 +1271,9 @@ xml_cdata(void *userData, const XML_Char *s, int len)
struct xml_ctx *ctx = (struct xml_ctx *)userData;
free(ctx->cdata);
ctx->cdata = xmalloc(len + 1);
- strlcpy(ctx->cdata, s, len + 1);
+ /* NB: 's' is not null-terminated, can not use strlcpy here */
+ memcpy(ctx->cdata, s, len);
+ ctx->cdata[len] = '\0';
}
static struct remote_lock *lock_remote(const char *path, long timeout)
@@ -1473,7 +1475,8 @@ static void process_ls_object(struct remote_ls_ctx *ls)
return;
path += 8;
obj_hex = xmalloc(strlen(path));
- strlcpy(obj_hex, path, 3);
+ /* NB: path is not null-terminated, can not use strlcpy here */
+ memcpy(obj_hex, path, 2);
strcpy(obj_hex + 2, path + 3);
one_remote_object(obj_hex);
free(obj_hex);
@@ -2170,7 +2173,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
/* If it's a symref, set the refname; otherwise try for a sha1 */
if (!prefixcmp((char *)buffer.buffer, "ref: ")) {
*symref = xmalloc(buffer.posn - 5);
- strlcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5);
+ memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6);
+ (*symref)[buffer.posn - 6] = '\0';
} else {
get_sha1_hex(buffer.buffer, sha1);
}
diff --git a/log-tree.c b/log-tree.c
index ac86194047..6ce239d8f9 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -211,7 +211,7 @@ void show_log(struct rev_info *opt, const char *sep)
sha1, sha1);
opt->diffopt.stat_sep = buffer;
}
- } else {
+ } else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
stdout);
if (opt->commit_format != CMIT_FMT_ONELINE)
diff --git a/refs.c b/refs.c
index d347876c87..7a1f89caad 100644
--- a/refs.c
+++ b/refs.c
@@ -1042,7 +1042,9 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
return -1;
}
+#ifndef NO_SYMLINK_HEAD
done:
+#endif
if (logmsg && !read_ref(refs_heads_master, new_sha1))
log_ref_write(ref_target, old_sha1, new_sha1, logmsg);
diff --git a/templates/hooks--update b/templates/hooks--update
index fd1f73d6aa..5b82b68e93 100644
--- a/templates/hooks--update
+++ b/templates/hooks--update
@@ -64,7 +64,7 @@ case "$refname","$newrev_type" in
# un-annotated tag
refname_type="tag"
short_refname=${refname##refs/tags/}
- if [ $allowunannotated != "true" ]; then
+ if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
@@ -148,7 +148,7 @@ case "$refname_type" in
# This shows all log entries that are not already covered by
# another ref - i.e. commits that are now accessible from this
# ref that were previously not accessible
- git-rev-parse --not --all | git-rev-list --stdin --pretty $newref
+ git log $newrev --not --all
echo $LOGEND
else
# oldrev is valid
@@ -165,7 +165,7 @@ case "$refname_type" in
baserev=$(git-merge-base $oldrev $newrev)
# Commit with a parent
- for rev in $(git-rev-parse --not --all | git-rev-list --stdin $newrev ^$baserev)
+ for rev in $(git-rev-list $newrev --not $baserev --all)
do
revtype=$(git-cat-file -t "$rev")
echo " via $rev ($revtype)"
@@ -190,12 +190,11 @@ case "$refname_type" in
fi
echo ""
echo $LOGBEGIN
- git-rev-parse --not --all |
- git-rev-list --stdin --pretty $newrev ^$baserev
+ git log $newrev --not $baserev --all
echo $LOGEND
echo ""
echo "Diffstat:"
- git-diff-tree --no-color --stat -M -C --find-copies-harder $newrev ^$baserev
+ git-diff-tree --no-color --stat -M -C --find-copies-harder $baserev..$newrev
fi
;;
"annotated tag")
diff --git a/utf8.c b/utf8.c
index 7c80eeccb4..a2965c9c11 100644
--- a/utf8.c
+++ b/utf8.c
@@ -3,13 +3,15 @@
/* This code is originally from http://www.cl.cam.ac.uk/~mgk25/ucs/ */
+typedef unsigned int ucs_char_t; /* assuming 32bit int */
+
struct interval {
int first;
int last;
};
/* auxiliary function for binary search in interval table */
-static int bisearch(wchar_t ucs, const struct interval *table, int max) {
+static int bisearch(ucs_char_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
@@ -56,11 +58,11 @@ static int bisearch(wchar_t ucs, const struct interval *table, int max) {
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
- * This implementation assumes that wchar_t characters are encoded
+ * This implementation assumes that ucs_char_t characters are encoded
* in ISO 10646.
*/
-static int wcwidth(wchar_t ch)
+static int wcwidth(ucs_char_t ch)
{
/*
* Sorted list of non-overlapping intervals of non-spacing characters,
@@ -157,7 +159,7 @@ static int wcwidth(wchar_t ch)
int utf8_width(const char **start)
{
unsigned char *s = (unsigned char *)*start;
- wchar_t ch;
+ ucs_char_t ch;
if (*s < 0x80) {
/* 0xxxxxxx */
@@ -235,12 +237,19 @@ static void print_spaces(int count)
/*
* Wrap the text, if necessary. The variable indent is the indent for the
* first line, indent2 is the indent for all other lines.
+ * If indent is negative, assume that already -indent columns have been
+ * consumed (and no extra indent is necessary for the first line).
*/
-void print_wrapped_text(const char *text, int indent, int indent2, int width)
+int print_wrapped_text(const char *text, int indent, int indent2, int width)
{
int w = indent, assume_utf8 = is_utf8(text);
const char *bol = text, *space = NULL;
+ if (indent < 0) {
+ w = -indent;
+ space = text;
+ }
+
for (;;) {
char c = *text;
if (!c || isspace(c)) {
@@ -251,10 +260,9 @@ void print_wrapped_text(const char *text, int indent, int indent2, int width)
else
print_spaces(indent);
fwrite(start, text - start, 1, stdout);
- if (!c) {
- putchar('\n');
- return;
- } else if (c == '\t')
+ if (!c)
+ return w;
+ else if (c == '\t')
w |= 0x07;
space = text;
w++;
@@ -262,7 +270,7 @@ void print_wrapped_text(const char *text, int indent, int indent2, int width)
}
else {
putchar('\n');
- text = bol = space + 1;
+ text = bol = space + isspace(*space);
space = NULL;
w = indent = indent2;
}
@@ -275,6 +283,7 @@ void print_wrapped_text(const char *text, int indent, int indent2, int width)
text++;
}
}
+ return w;
}
int is_encoding_utf8(const char *name)
@@ -291,11 +300,17 @@ int is_encoding_utf8(const char *name)
* with iconv. If the conversion fails, returns NULL.
*/
#ifndef NO_ICONV
+#ifdef OLD_ICONV
+ typedef const char * iconv_ibp;
+#else
+ typedef char * iconv_ibp;
+#endif
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding)
{
iconv_t conv;
size_t insz, outsz, outalloc;
- char *out, *outpos, *cp;
+ char *out, *outpos;
+ iconv_ibp cp;
if (!in_encoding)
return NULL;
@@ -307,7 +322,7 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e
outalloc = outsz + 1; /* for terminating NUL */
out = xmalloc(outalloc);
outpos = out;
- cp = (char *)in;
+ cp = (iconv_ibp)in;
while (1) {
size_t cnt = iconv(conv, &cp, &insz, &outpos, &outsz);
diff --git a/utf8.h b/utf8.h
index a07c5a88af..15db6f1f27 100644
--- a/utf8.h
+++ b/utf8.h
@@ -5,7 +5,7 @@ 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);
+int print_wrapped_text(const char *text, int indent, int indent2, int len);
#ifndef NO_ICONV
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);