diff options
-rw-r--r-- | Documentation/RelNotes-1.5.1.txt | 2 | ||||
-rwxr-xr-x | Documentation/build-docdep.perl | 6 | ||||
-rw-r--r-- | Documentation/config.txt | 5 | ||||
-rw-r--r-- | Documentation/git-add.txt | 2 | ||||
-rw-r--r-- | Documentation/git-branch.txt | 6 | ||||
-rw-r--r-- | Documentation/git-bundle.txt | 8 | ||||
-rw-r--r-- | Documentation/git-quiltimport.txt | 8 | ||||
-rw-r--r-- | Documentation/git-send-email.txt | 12 | ||||
-rw-r--r-- | Documentation/git-svn.txt | 121 | ||||
-rw-r--r-- | Documentation/pretty-formats.txt | 44 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | builtin-archive.c | 2 | ||||
-rw-r--r-- | builtin-branch.c | 12 | ||||
-rw-r--r-- | cache.h | 3 | ||||
-rw-r--r-- | commit.c | 195 | ||||
-rw-r--r-- | commit.h | 1 | ||||
-rw-r--r-- | date.c | 20 | ||||
-rw-r--r-- | git-compat-util.h | 6 | ||||
-rwxr-xr-x | git-gc.sh | 2 | ||||
-rwxr-xr-x | git-merge.sh | 2 | ||||
-rw-r--r-- | git.c | 2 | ||||
-rw-r--r-- | http-push.c | 10 | ||||
-rw-r--r-- | log-tree.c | 2 | ||||
-rw-r--r-- | refs.c | 2 | ||||
-rw-r--r-- | templates/hooks--update | 11 | ||||
-rw-r--r-- | utf8.c | 39 | ||||
-rw-r--r-- | utf8.h | 2 |
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. + @@ -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")) { @@ -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); @@ -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); @@ -47,6 +47,7 @@ enum cmit_fmt { CMIT_FMT_FULLER, CMIT_FMT_ONELINE, CMIT_FMT_EMAIL, + CMIT_FMT_USERFORMAT, CMIT_FMT_UNSPECIFIED, }; @@ -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> @@ -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 ;; @@ -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) @@ -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") @@ -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); @@ -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); |