diff options
43 files changed, 1058 insertions, 238 deletions
diff --git a/Documentation/RelNotes-1.5.4.5.txt b/Documentation/RelNotes-1.5.4.5.txt index 56fcd27b5c..0282341398 100644 --- a/Documentation/RelNotes-1.5.4.5.txt +++ b/Documentation/RelNotes-1.5.4.5.txt @@ -54,9 +54,3 @@ Fixes since v1.5.4.4 "rebase --continue" impossible. As usual, it also comes with many documentation fixes and clarifications. - --- -exec >/var/tmp/1 -echo O=$(git describe maint) -O=v1.5.4.4-32-gb88605f -git shortlog --no-merges $O..maint diff --git a/Documentation/RelNotes-1.5.5.txt b/Documentation/RelNotes-1.5.5.txt index b299e8792c..2932212488 100644 --- a/Documentation/RelNotes-1.5.5.txt +++ b/Documentation/RelNotes-1.5.5.txt @@ -6,7 +6,7 @@ Updates since v1.5.4 (subsystems) - * Comes with git-gui 0.9.3. + * Comes with git-gui 0.10.1 (portability) @@ -166,8 +166,8 @@ Updates since v1.5.4 symmetric difference between the HEAD version and the work tree version of the submodule commits. - * Various "git cvsimport", "git cvsexportcommit", "git svn" and - "git p4" improvements. + * Various "git cvsimport", "git cvsexportcommit", "git cvsserver", + "git svn" and "git p4" improvements. (internal) @@ -205,9 +205,3 @@ this release, unless otherwise noted. * "git imap-send" without setting imap.host did not error out but segfaulted. - ---- -exec >/var/tmp/1 -O=v1.5.5-rc1-21-g319a36a -echo O=`git describe refs/heads/master` -git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/config.txt b/Documentation/config.txt index 3017d640cf..04c01c5fdc 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -661,6 +661,13 @@ gitcvs.dbuser, gitcvs.dbpass:: 'gitcvs.dbuser' supports variable substitution (see linkgit:git-cvsserver[1] for details). +gitcvs.dbTableNamePrefix:: + Database table name prefix. Prepended to the names of any + database tables used, allowing a single database to be used + for several repositories. Supports variable substitution (see + linkgit:git-cvsserver[1] for details). Any non-alphabetic + characters will be replaced with underscores. + All gitcvs variables except for 'gitcvs.allbinary' can also be specified as 'gitcvs.<access_method>.<varname>' (where 'access_method' is one of "ext" and "pserver") to make them apply only for the given diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index c751a17d07..35e67a06e4 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -226,6 +226,12 @@ diff:: This lets you review what will be committed (i.e. between HEAD and index). +Bugs +---- +The interactive mode does not work with files whose names contain +characters that need C-quoting. `core.quotepath` configuration can be +used to work this limitation around to some degree, but backslash, +double-quote and control characters will still have problems. See Also -------- diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index d3e99931d7..9cec8021b8 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -227,6 +227,11 @@ gitcvs.dbpass:: Database password. Only useful if setting `dbdriver`, since SQLite has no concept of database passwords. +gitcvs.dbTableNamePrefix:: + Database table name prefix. Supports variable substitution + (see below). Any non-alphabetic characters will be replaced + with underscores. + All variables can also be set per access method, see <<configaccessmethod,above>>. Variable substitution diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index eed0a94c6e..3a1be08186 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -22,8 +22,9 @@ archive with specified base-name, or to the standard output. A packed archive is an efficient way to transfer set of objects between two repositories, and also is an archival format which is efficient to access. The packed archive format (.pack) is -designed to be unpackable without having anything else, but for -random access, accompanied with the pack index file (.idx). +designed to be self contained so that it can be unpacked without +any further information, but for fast, random access to the objects +in the pack, a pack index file (.idx) will be generated. Placing both in the pack/ subdirectory of $GIT_OBJECT_DIRECTORY (or any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES) diff --git a/Documentation/git.txt b/Documentation/git.txt index 3ed24d449a..336fe99cc7 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,15 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.5.4.4/git.html[documentation for release 1.5.4.4] +* link:v1.5.5/git.html[documentation for release 1.5.5] * release notes for + link:RelNotes-1.5.5.txt[1.5.5]. + +* link:v1.5.4.5/git.html[documentation for release 1.5.4.5] + +* release notes for + link:RelNotes-1.5.4.5.txt[1.5.4.5], link:RelNotes-1.5.4.4.txt[1.5.4.4], link:RelNotes-1.5.4.3.txt[1.5.4.3], link:RelNotes-1.5.4.2.txt[1.5.4.2], diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 0193c3ce58..e8bea3e18e 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -123,3 +123,4 @@ The placeholders are: - '%Creset': reset color - '%m': left, right or boundary mark - '%n': newline +- '%x00': print a byte from a hex code diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index aa87756a55..1803e64e46 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -103,10 +103,24 @@ Pack file entry: <+ packed object data: If it is not DELTA, then deflated bytes (the size above is the size before compression). - If it is DELTA, then + If it is REF_DELTA, then 20-byte base object name SHA1 (the size above is the size of the delta data that follows). delta data, deflated. + If it is OFS_DELTA, then + n-byte offset (see below) interpreted as a negative + offset from the type-byte of the header of the + ofs-delta entry (the size above is the size of + the delta data that follows). + delta data, deflated. + + offset encoding: + n bytes with MSB set in all but the last one. + The offset is then the number constructed by + concatenating the lower 7 bit of each byte, and + for n >= 2 adding 2^7 + 2^14 + ... + 2^(7*(n-1)) + to the result. + = Version 2 pack-*.idx files support packs larger than 4 GiB, and diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index d0b60f40d8..f60bab896b 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.5-rc1.GIT +DEF_VER=v1.5.5.GIT LF=' ' diff --git a/builtin-apply.c b/builtin-apply.c index b5f78ac3a7..abe73a0f81 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1937,21 +1937,24 @@ static int apply_one_fragment(struct image *img, struct fragment *frag, trailing = frag->trailing; /* - * If we don't have any leading/trailing data in the patch, - * we want it to match at the beginning/end of the file. + * A hunk to change lines at the beginning would begin with + * @@ -1,L +N,M @@ * - * But that would break if the patch is generated with - * --unified=0; sane people wouldn't do that to cause us - * trouble, but we try to please not so sane ones as well. + * And a hunk to add to an empty file would begin with + * @@ -0,0 +N,M @@ + * + * In other words, a hunk that is (frag->oldpos <= 1) with or + * without leading context must match at the beginning. */ - if (unidiff_zero) { - match_beginning = (!leading && !frag->oldpos); - match_end = 0; - } - else { - match_beginning = !leading && (frag->oldpos == 1); - match_end = !trailing; - } + match_beginning = frag->oldpos <= 1; + + /* + * A hunk without trailing lines must match at the end. + * However, we simply cannot tell if a hunk must match end + * from the lack of trailing lines if the patch was generated + * with unidiff without any context. + */ + match_end = !unidiff_zero && !trailing; pos = frag->newpos ? (frag->newpos - 1) : 0; preimage.buf = oldlines; diff --git a/builtin-fetch.c b/builtin-fetch.c index a11548c894..5841b3e51a 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -637,6 +637,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (!strcmp(argv[i], "tag")) { char *ref; i++; + if (i >= argc) + die("You need to specify a tag name."); ref = xmalloc(strlen(argv[i]) * 2 + 22); strcpy(ref, "refs/tags/"); strcat(ref, argv[i]); diff --git a/builtin-prune.c b/builtin-prune.c index bb8ead92cf..25f9304b82 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -4,8 +4,12 @@ #include "revision.h" #include "builtin.h" #include "reachable.h" +#include "parse-options.h" -static const char prune_usage[] = "git-prune [-n]"; +static const char * const prune_usage[] = { + "git-prune [-n] [--expire <time>] [--] [<head>...]", + NULL +}; static int show_only; static unsigned long expire; @@ -123,32 +127,33 @@ static void remove_temporary_files(void) int cmd_prune(int argc, const char **argv, const char *prefix) { - int i; struct rev_info revs; - - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (!strcmp(arg, "-n")) { - show_only = 1; - continue; - } - if (!strcmp(arg, "--expire")) { - if (++i < argc) { - expire = approxidate(argv[i]); - continue; - } - } - else if (!prefixcmp(arg, "--expire=")) { - expire = approxidate(arg + 9); - continue; - } - usage(prune_usage); - } + const struct option options[] = { + OPT_BOOLEAN('n', NULL, &show_only, + "do not remove, show only"), + OPT_DATE(0, "expire", &expire, + "expire objects older than <time>"), + OPT_END() + }; save_commit_buffer = 0; init_revisions(&revs, prefix); - mark_reachable_objects(&revs, 1); + argc = parse_options(argc, argv, options, prune_usage, 0); + while (argc--) { + unsigned char sha1[20]; + const char *name = *argv++; + + if (!get_sha1(name, sha1)) { + struct object *object = parse_object(sha1); + if (!object) + die("bad object: %s", name); + add_pending_object(&revs, object, ""); + } + else + die("unrecognized argument: %s", name); + } + mark_reachable_objects(&revs, 1); prune_object_dir(get_object_directory()); sync(); diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c index f3ef11fa2d..db81496b46 100644 --- a/builtin-verify-tag.c +++ b/builtin-verify-tag.c @@ -46,8 +46,10 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose) gpg.argv = args_gpg; gpg.in = -1; args_gpg[2] = path; - if (start_command(&gpg)) + if (start_command(&gpg)) { + unlink(path); return error("could not run gpg."); + } write_in_full(gpg.in, buf, len); close(gpg.in); diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 5046f69934..4d81963b1d 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -639,7 +639,9 @@ _git_diff () --find-copies-harder --pickaxe-all --pickaxe-regex --text --ignore-space-at-eol --ignore-space-change --ignore-all-space --exit-code --quiet --ext-diff - --no-ext-diff" + --no-ext-diff + --no-prefix --src-prefix= --dst-prefix= + " return ;; esac @@ -696,6 +698,7 @@ _git_format_patch () --full-index --binary --not --all --cover-letter + --no-prefix --src-prefix= --dst-prefix= " return ;; @@ -865,7 +868,7 @@ _git_rebase () return ;; --*) - __gitcomp "--onto --merge --strategy" + __gitcomp "--onto --merge --strategy --interactive" return esac __gitcomp "$(__git_refs)" @@ -999,7 +1002,8 @@ _git_config () gitcvs.enabled gitcvs.logfile gitcvs.allbinary - gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dvpass + gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dbpass + gitcvs.dbtablenameprefix gc.packrefs gc.reflogexpire gc.reflogexpireunreachable diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3cb0330ec2..d8de9f6c25 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -90,11 +90,11 @@ def getP4OpenedType(file): # Returns the perforce file type for the given file. result = read_pipe("p4 opened %s" % file) - match = re.match(".*\((.+)\)$", result) + match = re.match(".*\((.+)\)\r?$", result) if match: return match.group(1) else: - die("Could not determine file type for %s" % file) + die("Could not determine file type for %s (result: '%s')" % (file, result)) def diffTreePattern(): # This is a simple generator for the diff tree regex pattern. This could be @@ -513,6 +513,8 @@ class P4Submit(Command): template = "" inFilesSection = False for line in read_pipe_lines("p4 change -o"): + if line.endswith("\r\n"): + line = line[:-2] + "\n" if inFilesSection: if line.startswith("\t"): # path starts and ends with a tab @@ -619,8 +621,6 @@ class P4Submit(Command): setP4ExecBit(f, mode) logMessage = extractLogMessageFromGitCommit(id) - if self.isWindows: - logMessage = logMessage.replace("\n", "\r\n") logMessage = logMessage.strip() template = self.prepareSubmitTemplate() @@ -631,23 +631,25 @@ class P4Submit(Command): del(os.environ["P4DIFF"]) diff = read_pipe("p4 diff -du ...") + newdiff = "" for newFile in filesToAdd: - diff += "==== new file ====\n" - diff += "--- /dev/null\n" - diff += "+++ %s\n" % newFile + newdiff += "==== new file ====\n" + newdiff += "--- /dev/null\n" + newdiff += "+++ %s\n" % newFile f = open(newFile, "r") for line in f.readlines(): - diff += "+" + line + newdiff += "+" + line f.close() - separatorLine = "######## everything below this line is just the diff #######" - if platform.system() == "Windows": - separatorLine += "\r" - separatorLine += "\n" + separatorLine = "######## everything below this line is just the diff #######\n" [handle, fileName] = tempfile.mkstemp() tmpFile = os.fdopen(handle, "w+") - tmpFile.write(submitTemplate + separatorLine + diff) + if self.isWindows: + submitTemplate = submitTemplate.replace("\n", "\r\n") + separatorLine = separatorLine.replace("\n", "\r\n") + newdiff = newdiff.replace("\n", "\r\n") + tmpFile.write(submitTemplate + separatorLine + diff + newdiff) tmpFile.close() defaultEditor = "vi" if platform.system() == "Windows": diff --git a/diff-lib.c b/diff-lib.c index 52dbac34a4..069e4507ae 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -10,6 +10,7 @@ #include "cache-tree.h" #include "path-list.h" #include "unpack-trees.h" +#include "refs.h" /* * diff-files @@ -333,6 +334,26 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) } return run_diff_files(revs, options); } +/* + * See if work tree has an entity that can be staged. Return 0 if so, + * return 1 if not and return -1 if error. + */ +static int check_work_tree_entity(const struct cache_entry *ce, struct stat *st, char *symcache) +{ + if (lstat(ce->name, st) < 0) { + if (errno != ENOENT && errno != ENOTDIR) + return -1; + return 1; + } + if (has_symlink_leading_path(ce->name, symcache)) + return 1; + if (S_ISDIR(st->st_mode)) { + unsigned char sub[20]; + if (resolve_gitlink_ref(ce->name, "HEAD", sub)) + return 1; + } + return 0; +} int run_diff_files(struct rev_info *revs, unsigned int option) { @@ -341,10 +362,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option) int silent_on_removed = option & DIFF_SILENT_ON_REMOVED; unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); + char symcache[PATH_MAX]; if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; entries = active_nr; + symcache[0] = '\0'; for (i = 0; i < entries; i++) { struct stat st; unsigned int oldmode, newmode; @@ -376,16 +399,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option) memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); - if (lstat(ce->name, &st) < 0) { - if (errno != ENOENT && errno != ENOTDIR) { + changed = check_work_tree_entity(ce, &st, symcache); + if (!changed) + dpath->mode = ce_mode_from_stat(ce, st.st_mode); + else { + if (changed < 0) { perror(ce->name); continue; } if (silent_on_removed) continue; } - else - dpath->mode = ce_mode_from_stat(ce, st.st_mode); while (i < entries) { struct cache_entry *nce = active_cache[i]; @@ -438,8 +462,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (ce_uptodate(ce)) continue; - if (lstat(ce->name, &st) < 0) { - if (errno != ENOENT && errno != ENOTDIR) { + + changed = check_work_tree_entity(ce, &st, symcache); + if (changed) { + if (changed < 0) { perror(ce->name); continue; } @@ -468,6 +494,11 @@ int run_diff_files(struct rev_info *revs, unsigned int option) * diff-index */ +struct oneway_unpack_data { + struct rev_info *revs; + char symcache[PATH_MAX]; +}; + /* A file entry went away or appeared */ static void diff_index_show_file(struct rev_info *revs, const char *prefix, @@ -481,7 +512,8 @@ static void diff_index_show_file(struct rev_info *revs, static int get_stat_data(struct cache_entry *ce, const unsigned char **sha1p, unsigned int *modep, - int cached, int match_missing) + int cached, int match_missing, + struct oneway_unpack_data *cbdata) { const unsigned char *sha1 = ce->sha1; unsigned int mode = ce->ce_mode; @@ -489,8 +521,11 @@ static int get_stat_data(struct cache_entry *ce, if (!cached) { int changed; struct stat st; - if (lstat(ce->name, &st) < 0) { - if (errno == ENOENT && match_missing) { + changed = check_work_tree_entity(ce, &st, cbdata->symcache); + if (changed < 0) + return -1; + else if (changed) { + if (match_missing) { *sha1p = sha1; *modep = mode; return 0; @@ -509,23 +544,25 @@ static int get_stat_data(struct cache_entry *ce, return 0; } -static void show_new_file(struct rev_info *revs, +static void show_new_file(struct oneway_unpack_data *cbdata, struct cache_entry *new, int cached, int match_missing) { const unsigned char *sha1; unsigned int mode; + struct rev_info *revs = cbdata->revs; - /* New file in the index: it might actually be different in + /* + * New file in the index: it might actually be different in * the working copy. */ - if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) + if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) return; diff_index_show_file(revs, "+", new, sha1, mode); } -static int show_modified(struct rev_info *revs, +static int show_modified(struct oneway_unpack_data *cbdata, struct cache_entry *old, struct cache_entry *new, int report_missing, @@ -533,8 +570,9 @@ static int show_modified(struct rev_info *revs, { unsigned int mode, oldmode; const unsigned char *sha1; + struct rev_info *revs = cbdata->revs; - if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) { + if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, old->sha1, old->ce_mode); @@ -602,7 +640,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct cache_entry *idx, struct cache_entry *tree) { - struct rev_info *revs = o->unpack_data; + struct oneway_unpack_data *cbdata = o->unpack_data; + struct rev_info *revs = cbdata->revs; int match_missing, cached; /* @@ -625,7 +664,7 @@ static void do_oneway_diff(struct unpack_trees_options *o, * Something added to the tree? */ if (!tree) { - show_new_file(revs, idx, cached, match_missing); + show_new_file(cbdata, idx, cached, match_missing); return; } @@ -638,7 +677,7 @@ static void do_oneway_diff(struct unpack_trees_options *o, } /* Show difference between old and new */ - show_modified(revs, tree, idx, 1, cached, match_missing); + show_modified(cbdata, tree, idx, 1, cached, match_missing); } static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o) @@ -675,7 +714,8 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o) { struct cache_entry *idx = src[0]; struct cache_entry *tree = src[1]; - struct rev_info *revs = o->unpack_data; + struct oneway_unpack_data *cbdata = o->unpack_data; + struct rev_info *revs = cbdata->revs; if (idx && ce_stage(idx)) skip_same_name(idx, o); @@ -702,6 +742,7 @@ int run_diff_index(struct rev_info *revs, int cached) const char *tree_name; struct unpack_trees_options opts; struct tree_desc t; + struct oneway_unpack_data unpack_cb; mark_merge_entries(); @@ -711,12 +752,14 @@ int run_diff_index(struct rev_info *revs, int cached) if (!tree) return error("bad tree object %s", tree_name); + unpack_cb.revs = revs; + unpack_cb.symcache[0] = '\0'; memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = cached; opts.merge = 1; opts.fn = oneway_diff; - opts.unpack_data = revs; + opts.unpack_data = &unpack_cb; opts.src_index = &the_index; opts.dst_index = NULL; @@ -738,6 +781,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) struct cache_entry *last = NULL; struct unpack_trees_options opts; struct tree_desc t; + struct oneway_unpack_data unpack_cb; /* * This is used by git-blame to run diff-cache internally; @@ -766,12 +810,14 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) if (!tree) die("bad tree object %s", sha1_to_hex(tree_sha1)); + unpack_cb.revs = &revs; + unpack_cb.symcache[0] = '\0'; memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = 1; opts.merge = 1; opts.fn = oneway_diff; - opts.unpack_data = &revs; + opts.unpack_data = &unpack_cb; opts.src_index = &the_index; opts.dst_index = &the_index; diff --git a/git-clone.sh b/git-clone.sh index e981122778..2636159aaa 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -310,6 +310,9 @@ yes) mkdir -p "$GIT_DIR/objects/info" echo "$repo/objects" >>"$GIT_DIR/objects/info/alternates" else + cpio_quiet_flag="" + cpio --help 2>&1 | grep -- --quiet >/dev/null && \ + cpio_quiet_flag=--quiet l= && if test "$use_local_hardlink" = yes then @@ -330,7 +333,8 @@ yes) fi fi && cd "$repo" && - find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1 + find objects -depth -print | cpio $cpio_quiet_flag -pumd$l "$GIT_DIR/" || \ + exit 1 fi git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1 ;; diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 7f632af20d..29dbfc940b 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -73,8 +73,8 @@ my $methods = { 'status' => \&req_status, 'admin' => \&req_CATCHALL, 'history' => \&req_CATCHALL, - 'watchers' => \&req_CATCHALL, - 'editors' => \&req_CATCHALL, + 'watchers' => \&req_EMPTY, + 'editors' => \&req_EMPTY, 'annotate' => \&req_annotate, 'Global_option' => \&req_Globaloption, #'annotate' => \&req_CATCHALL, @@ -199,6 +199,11 @@ sub req_CATCHALL $log->warn("Unhandled command : req_$cmd : $data"); } +# This method invariably succeeds with an empty response. +sub req_EMPTY +{ + print "ok\n"; +} # Root pathname \n # Response expected: no. Tell the server which CVSROOT to use. Note that @@ -958,6 +963,17 @@ sub req_update $meta = $updater->getmeta($filename); } + # If -p was given, "print" the contents of the requested revision. + if ( exists ( $state->{opt}{p} ) ) { + if ( defined ( $meta->{revision} ) ) { + $log->info("Printing '$filename' revision " . $meta->{revision}); + + transmitfile($meta->{filehash}, { print => 1 }); + } + + next; + } + if ( ! defined $meta ) { $meta = { @@ -1091,9 +1107,9 @@ sub req_update my $file_local = $filepart . ".mine"; system("ln","-s",$state->{entries}{$filename}{modified_filename}, $file_local); my $file_old = $filepart . "." . $oldmeta->{revision}; - transmitfile($oldmeta->{filehash}, $file_old); + transmitfile($oldmeta->{filehash}, { targetfile => $file_old }); my $file_new = $filepart . "." . $meta->{revision}; - transmitfile($meta->{filehash}, $file_new); + transmitfile($meta->{filehash}, { targetfile => $file_new }); # we need to merge with the local changes ( M=successful merge, C=conflict merge ) $log->info("Merging $file_local, $file_old, $file_new"); @@ -1423,6 +1439,8 @@ sub req_status { $filename = filecleanup($filename); + next if exists($state->{opt}{l}) && index($filename, '/', length($state->{prependdir})) >= 0; + my $meta = $updater->getmeta($filename); my $oldmeta = $meta; @@ -1466,8 +1484,10 @@ sub req_status $status ||= "Unknown"; + my ($filepart) = filenamesplit($filename); + print "M ===================================================================\n"; - print "M File: $filename\tStatus: $status\n"; + print "M File: $filepart\tStatus: $status\n"; if ( defined($state->{entries}{$filename}{revision}) ) { print "M Working revision:\t" . $state->{entries}{$filename}{revision} . "\n"; @@ -1541,14 +1561,14 @@ sub req_diff print "E File $filename at revision 1.$revision1 doesn't exist\n"; next; } - transmitfile($meta1->{filehash}, $file1); + transmitfile($meta1->{filehash}, { targetfile => $file1 }); } # otherwise we just use the working copy revision else { ( undef, $file1 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 ); $meta1 = $updater->getmeta($filename, $wrev); - transmitfile($meta1->{filehash}, $file1); + transmitfile($meta1->{filehash}, { targetfile => $file1 }); } # if we have a second -r switch, use it too @@ -1563,7 +1583,7 @@ sub req_diff next; } - transmitfile($meta2->{filehash}, $file2); + transmitfile($meta2->{filehash}, { targetfile => $file2 }); } # otherwise we just use the working copy else @@ -1576,7 +1596,7 @@ sub req_diff { ( undef, $file2 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 ); $meta2 = $updater->getmeta($filename, $wrev); - transmitfile($meta2->{filehash}, $file2); + transmitfile($meta2->{filehash}, { targetfile => $file2 }); } # We need to have retrieved something useful @@ -1708,8 +1728,7 @@ sub req_log print "M revision 1.$revision->{revision}\n"; # reformat the date for log output $revision->{modified} = sprintf('%04d/%02d/%02d %s', $3, $DATE_LIST->{$2}, $1, $4 ) if ( $revision->{modified} =~ /(\d+)\s+(\w+)\s+(\d+)\s+(\S+)/ and defined($DATE_LIST->{$2}) ); - $revision->{author} =~ s/\s+.*//; - $revision->{author} =~ s/^(.{8}).*/$1/; + $revision->{author} = cvs_author($revision->{author}); print "M date: $revision->{modified}; author: $revision->{author}; state: " . ( $revision->{filehash} eq "deleted" ? "dead" : "Exp" ) . "; lines: +2 -3\n"; my $commitmessage = $updater->commitmessage($revision->{commithash}); $commitmessage =~ s/^/M /mg; @@ -1824,8 +1843,7 @@ sub req_annotate unless ( defined ( $metadata->{$commithash} ) ) { $metadata->{$commithash} = $updater->getmeta($filename, $commithash); - $metadata->{$commithash}{author} =~ s/\s+.*//; - $metadata->{$commithash}{author} =~ s/^(.{8}).*/$1/; + $metadata->{$commithash}{author} = cvs_author($metadata->{$commithash}{author}); $metadata->{$commithash}{modified} = sprintf("%02d-%s-%02d", $1, $2, $3) if ( $metadata->{$commithash}{modified} =~ /^(\d+)\s(\w+)\s\d\d(\d\d)/ ); } printf("M 1.%-5d (%-8s %10s): %s\n", @@ -2005,14 +2023,17 @@ sub revparse return undef; } -# This method takes a file hash and does a CVS "file transfer" which transmits the -# size of the file, and then the file contents. -# If a second argument $targetfile is given, the file is instead written out to -# a file by the name of $targetfile +# This method takes a file hash and does a CVS "file transfer". Its +# exact behaviour depends on a second, optional hash table argument: +# - If $options->{targetfile}, dump the contents to that file; +# - If $options->{print}, use M/MT to transmit the contents one line +# at a time; +# - Otherwise, transmit the size of the file, followed by the file +# contents. sub transmitfile { my $filehash = shift; - my $targetfile = shift; + my $options = shift; if ( defined ( $filehash ) and $filehash eq "deleted" ) { @@ -2034,11 +2055,20 @@ sub transmitfile if ( open my $fh, '-|', "git-cat-file", "blob", $filehash ) { - if ( defined ( $targetfile ) ) + if ( defined ( $options->{targetfile} ) ) { + my $targetfile = $options->{targetfile}; open NEWFILE, ">", $targetfile or die("Couldn't open '$targetfile' for writing : $!"); print NEWFILE $_ while ( <$fh> ); close NEWFILE or die("Failed to write '$targetfile': $!"); + } elsif ( defined ( $options->{print} ) && $options->{print} ) { + while ( <$fh> ) { + if( /\n\z/ ) { + print 'M ', $_; + } else { + print 'MT text ', $_, "\n"; + } + } } else { print "$size\n"; print while ( <$fh> ); @@ -2107,6 +2137,16 @@ sub kopts_from_path } } +# Generate a CVS author name from Git author information, by taking +# the first eight characters of the user part of the email address. +sub cvs_author +{ + my $author_line = shift; + (my $author) = $author_line =~ /<([^>@]{1,8})/; + + $author; +} + package GITCVS::log; #### @@ -2311,6 +2351,14 @@ sub new bless $self, $class; + $self->{valid_tables} = {'revision' => 1, + 'revision_ix1' => 1, + 'revision_ix2' => 1, + 'head' => 1, + 'head_ix1' => 1, + 'properties' => 1, + 'commitmsgs' => 1}; + $self->{module} = $module; $self->{git_path} = $config . "/"; @@ -2326,6 +2374,8 @@ sub new $cfg->{gitcvs}{dbuser} || ""; $self->{dbpass} = $cfg->{gitcvs}{$state->{method}}{dbpass} || $cfg->{gitcvs}{dbpass} || ""; + $self->{dbtablenameprefix} = $cfg->{gitcvs}{$state->{method}}{dbtablenameprefix} || + $cfg->{gitcvs}{dbtablenameprefix} || ""; my %mapping = ( m => $module, a => $state->{method}, u => getlogin || getpwuid($<) || $<, @@ -2334,6 +2384,8 @@ sub new ); $self->{dbname} =~ s/%([mauGg])/$mapping{$1}/eg; $self->{dbuser} =~ s/%([mauGg])/$mapping{$1}/eg; + $self->{dbtablenameprefix} =~ s/%([mauGg])/$mapping{$1}/eg; + $self->{dbtablenameprefix} = mangle_tablename($self->{dbtablenameprefix}); die "Invalid char ':' in dbdriver" if $self->{dbdriver} =~ /:/; die "Invalid char ';' in dbname" if $self->{dbname} =~ /;/; @@ -2349,10 +2401,13 @@ sub new } # Construct the revision table if required - unless ( $self->{tables}{revision} ) + unless ( $self->{tables}{$self->tablename("revision")} ) { + my $tablename = $self->tablename("revision"); + my $ix1name = $self->tablename("revision_ix1"); + my $ix2name = $self->tablename("revision_ix2"); $self->{dbh}->do(" - CREATE TABLE revision ( + CREATE TABLE $tablename ( name TEXT NOT NULL, revision INTEGER NOT NULL, filehash TEXT NOT NULL, @@ -2363,20 +2418,22 @@ sub new ) "); $self->{dbh}->do(" - CREATE INDEX revision_ix1 - ON revision (name,revision) + CREATE INDEX $ix1name + ON $tablename (name,revision) "); $self->{dbh}->do(" - CREATE INDEX revision_ix2 - ON revision (name,commithash) + CREATE INDEX $ix2name + ON $tablename (name,commithash) "); } # Construct the head table if required - unless ( $self->{tables}{head} ) + unless ( $self->{tables}{$self->tablename("head")} ) { + my $tablename = $self->tablename("head"); + my $ix1name = $self->tablename("head_ix1"); $self->{dbh}->do(" - CREATE TABLE head ( + CREATE TABLE $tablename ( name TEXT NOT NULL, revision INTEGER NOT NULL, filehash TEXT NOT NULL, @@ -2387,16 +2444,17 @@ sub new ) "); $self->{dbh}->do(" - CREATE INDEX head_ix1 - ON head (name) + CREATE INDEX $ix1name + ON $tablename (name) "); } # Construct the properties table if required - unless ( $self->{tables}{properties} ) + unless ( $self->{tables}{$self->tablename("properties")} ) { + my $tablename = $self->tablename("properties"); $self->{dbh}->do(" - CREATE TABLE properties ( + CREATE TABLE $tablename ( key TEXT NOT NULL PRIMARY KEY, value TEXT ) @@ -2404,10 +2462,11 @@ sub new } # Construct the commitmsgs table if required - unless ( $self->{tables}{commitmsgs} ) + unless ( $self->{tables}{$self->tablename("commitmsgs")} ) { + my $tablename = $self->tablename("commitmsgs"); $self->{dbh}->do(" - CREATE TABLE commitmsgs ( + CREATE TABLE $tablename ( key TEXT NOT NULL PRIMARY KEY, value TEXT ) @@ -2417,6 +2476,21 @@ sub new return $self; } +=head2 tablename + +=cut +sub tablename +{ + my $self = shift; + my $name = shift; + + if (exists $self->{valid_tables}{$name}) { + return $self->{dbtablenameprefix} . $name; + } else { + return undef; + } +} + =head2 update =cut @@ -2633,7 +2707,7 @@ sub update }; $self->insert_rev($name, $head->{$name}{revision}, $hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); } - elsif ( $change eq "M" ) + elsif ( $change eq "M" || $change eq "T" ) { #$log->debug("MODIFIED $name"); $head->{$name} = { @@ -2782,8 +2856,9 @@ sub insert_rev my $modified = shift; my $author = shift; my $mode = shift; + my $tablename = $self->tablename("revision"); - my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); + my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); $insert_rev->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode); } @@ -2792,16 +2867,18 @@ sub insert_mergelog my $self = shift; my $key = shift; my $value = shift; + my $tablename = $self->tablename("commitmsgs"); - my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1); + my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1); $insert_mergelog->execute($key, $value); } sub delete_head { my $self = shift; + my $tablename = $self->tablename("head"); - my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1); + my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM $tablename",{},1); $delete_head->execute(); } @@ -2815,8 +2892,9 @@ sub insert_head my $modified = shift; my $author = shift; my $mode = shift; + my $tablename = $self->tablename("head"); - my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); + my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); $insert_head->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode); } @@ -2824,8 +2902,9 @@ sub _headrev { my $self = shift; my $filename = shift; + my $tablename = $self->tablename("head"); - my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM head WHERE name=?",{},1); + my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM $tablename WHERE name=?",{},1); $db_query->execute($filename); my ( $hash, $revision, $mode ) = $db_query->fetchrow_array; @@ -2836,8 +2915,9 @@ sub _get_prop { my $self = shift; my $key = shift; + my $tablename = $self->tablename("properties"); - my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM properties WHERE key=?",{},1); + my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1); $db_query->execute($key); my ( $value ) = $db_query->fetchrow_array; @@ -2849,13 +2929,14 @@ sub _set_prop my $self = shift; my $key = shift; my $value = shift; + my $tablename = $self->tablename("properties"); - my $db_query = $self->{dbh}->prepare_cached("UPDATE properties SET value=? WHERE key=?",{},1); + my $db_query = $self->{dbh}->prepare_cached("UPDATE $tablename SET value=? WHERE key=?",{},1); $db_query->execute($value, $key); unless ( $db_query->rows ) { - $db_query = $self->{dbh}->prepare_cached("INSERT INTO properties (key, value) VALUES (?,?)",{},1); + $db_query = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1); $db_query->execute($key, $value); } @@ -2869,10 +2950,11 @@ sub _set_prop sub gethead { my $self = shift; + my $tablename = $self->tablename("head"); return $self->{gethead_cache} if ( defined ( $self->{gethead_cache} ) ); - my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM head ORDER BY name ASC",{},1); + my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM $tablename ORDER BY name ASC",{},1); $db_query->execute(); my $tree = []; @@ -2894,8 +2976,9 @@ sub getlog { my $self = shift; my $filename = shift; + my $tablename = $self->tablename("revision"); - my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1); + my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1); $db_query->execute($filename); my $tree = []; @@ -2919,19 +3002,21 @@ sub getmeta my $self = shift; my $filename = shift; my $revision = shift; + my $tablename_rev = $self->tablename("revision"); + my $tablename_head = $self->tablename("head"); my $db_query; if ( defined($revision) and $revision =~ /^\d+$/ ) { - $db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND revision=?",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND revision=?",{},1); $db_query->execute($filename, $revision); } elsif ( defined($revision) and $revision =~ /^[a-zA-Z0-9]{40}$/ ) { - $db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND commithash=?",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND commithash=?",{},1); $db_query->execute($filename, $revision); } else { - $db_query = $self->{dbh}->prepare_cached("SELECT * FROM head WHERE name=?",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_head WHERE name=?",{},1); $db_query->execute($filename); } @@ -2947,11 +3032,12 @@ sub commitmessage { my $self = shift; my $commithash = shift; + my $tablename = $self->tablename("commitmsgs"); die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{40}$/ ); my $db_query; - $db_query = $self->{dbh}->prepare_cached("SELECT value FROM commitmsgs WHERE key=?",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1); $db_query->execute($commithash); my ( $message ) = $db_query->fetchrow_array; @@ -2979,9 +3065,10 @@ sub gethistory { my $self = shift; my $filename = shift; + my $tablename = $self->tablename("revision"); my $db_query; - $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1); $db_query->execute($filename); return $db_query->fetchall_arrayref; @@ -3001,9 +3088,10 @@ sub gethistorydense { my $self = shift; my $filename = shift; + my $tablename = $self->tablename("revision"); my $db_query; - $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1); + $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1); $db_query->execute($filename); return $db_query->fetchall_arrayref; @@ -3061,4 +3149,19 @@ sub mangle_dirname { return $dirname; } +=head2 mangle_tablename + +create a string from a that is suitable to use as part of an SQL table +name, mainly by converting all chars except \w to _ + +=cut +sub mangle_tablename { + my $tablename = shift; + return unless defined $tablename; + + $tablename =~ s/[^\w_]/_/g; + + return $tablename; +} + 1; diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 22b6ed4a78..ea59015baa 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -281,7 +281,7 @@ while read commit parents; do die "Could not checkout the index" # files that $commit removed are now still in the working tree; # remove them, else they would be added again - git clean -q -f -x + git clean -d -q -f -x eval "$filter_tree" < /dev/null || die "tree filter failed: $filter_tree" diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN index cfe46a857e..0ab478ef90 100755 --- a/git-gui/GIT-VERSION-GEN +++ b/git-gui/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=0.9.GITGUI +DEF_VER=0.10.GITGUI LF=' ' diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 5e97fbf03e..7c25bb9808 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -1846,6 +1846,22 @@ proc add_range_to_selection {w x y} { $w tag add in_sel $begin.0 [expr {$end + 1}].0 } +proc show_more_context {} { + global repo_config + if {$repo_config(gui.diffcontext) < 99} { + incr repo_config(gui.diffcontext) + reshow_diff + } +} + +proc show_less_context {} { + global repo_config + if {$repo_config(gui.diffcontext) >= 1} { + incr repo_config(gui.diffcontext) -1 + reshow_diff + } +} + ###################################################################### ## ## ui construction @@ -2046,6 +2062,16 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { .mbar.commit add separator + .mbar.commit add command -label [mc "Show Less Context"] \ + -command show_less_context \ + -accelerator $M1T-\- + + .mbar.commit add command -label [mc "Show More Context"] \ + -command show_more_context \ + -accelerator $M1T-= + + .mbar.commit add separator + .mbar.commit add command -label [mc "Sign Off"] \ -command do_signoff \ -accelerator $M1T-S @@ -2593,17 +2619,11 @@ lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] $ctxm add separator $ctxm add command \ -label [mc "Show Less Context"] \ - -command {if {$repo_config(gui.diffcontext) >= 1} { - incr repo_config(gui.diffcontext) -1 - reshow_diff - }} + -command show_less_context lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ -label [mc "Show More Context"] \ - -command {if {$repo_config(gui.diffcontext) < 99} { - incr repo_config(gui.diffcontext) - reshow_diff - }} + -command show_more_context lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator $ctxm add command \ @@ -2695,6 +2715,11 @@ bind $ui_comm <$M1B-Key-v> {tk_textPaste %W; %W see insert; break} bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break} bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break} bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break} +bind $ui_comm <$M1B-Key-minus> {show_less_context;break} +bind $ui_comm <$M1B-Key-KP_Subtract> {show_less_context;break} +bind $ui_comm <$M1B-Key-equal> {show_more_context;break} +bind $ui_comm <$M1B-Key-plus> {show_more_context;break} +bind $ui_comm <$M1B-Key-KP_Add> {show_more_context;break} bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break} bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break} @@ -2738,6 +2763,11 @@ bind . <$M1B-Key-t> do_add_selection bind . <$M1B-Key-T> do_add_selection bind . <$M1B-Key-i> do_add_all bind . <$M1B-Key-I> do_add_all +bind . <$M1B-Key-minus> {show_less_context;break} +bind . <$M1B-Key-KP_Subtract> {show_less_context;break} +bind . <$M1B-Key-equal> {show_more_context;break} +bind . <$M1B-Key-plus> {show_more_context;break} +bind . <$M1B-Key-KP_Add> {show_more_context;break} bind . <$M1B-Key-Return> do_commit foreach i [list $ui_index $ui_workdir] { bind $i <Button-1> "toggle_or_diff $i %x %y; break" diff --git a/git-gui/po/fr.po b/git-gui/po/fr.po index d281938e33..89b6d51ea0 100644 --- a/git-gui/po/fr.po +++ b/git-gui/po/fr.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: fr\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-14 07:18+0100\n" -"PO-Revision-Date: 2008-01-14 21:08+0100\n" +"PO-Revision-Date: 2008-04-04 22:05+0200\n" "Last-Translator: Christian Couder <chriscool@tuxfamily.org>\n" "Language-Team: French\n" "MIME-Version: 1.0\n" @@ -344,8 +344,7 @@ msgstr "Documentation en ligne" #: git-gui.sh:2238 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" -msgstr "" -"fatale : pas d'infos sur le chemin %s : Fichier ou répertoire inexistant" +msgstr "erreur fatale : pas d'infos sur le chemin %s : Fichier ou répertoire inexistant" #: git-gui.sh:2271 msgid "Current Branch:" @@ -630,8 +629,7 @@ msgstr "Merci de choisir une branche de suivi" #: lib/branch_create.tcl:140 #, tcl-format msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "" -"La branche de suivi %s n'est pas une branche dans le référentiel distant." +msgstr "La branche de suivi %s n'est pas une branche dans le référentiel distant." #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 msgid "Please supply a branch name." @@ -751,7 +749,7 @@ msgstr "Récupération de %s à partir de %s" #: lib/checkout_op.tcl:127 #, tcl-format msgid "fatal: Cannot resolve %s" -msgstr "Erreur fatale : Impossible de résoudre %s" +msgstr "erreur fatale : Impossible de résoudre %s" #: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 msgid "Close" @@ -798,12 +796,9 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"L'état lors de la dernière synchronisation ne correspond plus à l'état du " -"référentiel.\n" +"L'état lors de la dernière synchronisation ne correspond plus à l'état du référentiel.\n" "\n" -"Un autre programme Git a modifié ce référentiel depuis la dernière " -"synchronisation. Une resynchronisation doit être effectuée avant de pouvoir " -"modifier la branche courante.\n" +"Un autre programme Git a modifié ce référentiel depuis la dernière synchronisation. Une resynchronisation doit être effectuée avant de pouvoir modifier la branche courante.\n" "\n" "Cela va être fait tout de suite automatiquement.\n" @@ -814,13 +809,12 @@ msgstr "Mise à jour du répertoire courant avec '%s'..." #: lib/checkout_op.tcl:323 msgid "files checked out" -msgstr "" +msgstr "fichiers empruntés" #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "" -"Emprunt de '%s' abandonné. (Il est nécessaire de fusionner des fichiers.)" +msgstr "Emprunt de '%s' abandonné. (Il est nécessaire de fusionner des fichiers.)" #: lib/checkout_op.tcl:354 msgid "File level merge required." @@ -1089,8 +1083,7 @@ msgstr "" #: lib/choose_repository.tcl:880 msgid "Cannot determine HEAD. See console output for details." -msgstr "" -"Impossible de déterminer HEAD. Voir la sortie console pour plus de détails." +msgstr "Impossible de déterminer HEAD. Voir la sortie console pour plus de détails." #: lib/choose_repository.tcl:889 #, tcl-format @@ -1292,32 +1285,31 @@ msgstr "attention : Tcl ne supporte pas l'encodage '%s'." #: lib/commit.tcl:221 msgid "Calling pre-commit hook..." -msgstr "" +msgstr "Appel du programme externe d'avant commit..." #: lib/commit.tcl:236 msgid "Commit declined by pre-commit hook." -msgstr "" +msgstr "Commit refusé par le programme externe d'avant commit." #: lib/commit.tcl:259 msgid "Calling commit-msg hook..." -msgstr "" +msgstr "Appel du programme externe de message de commit..." #: lib/commit.tcl:274 msgid "Commit declined by commit-msg hook." -msgstr "" +msgstr "Commit refusé par le programme externe de message de commit." #: lib/commit.tcl:287 msgid "Committing changes..." -msgstr "" +msgstr "Commit des modifications..." #: lib/commit.tcl:303 msgid "write-tree failed:" msgstr "write-tree a échoué :" #: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368 -#, fuzzy msgid "Commit failed." -msgstr "Le clonage a échoué." +msgstr "Le commit a échoué." #: lib/commit.tcl:321 #, tcl-format @@ -1479,8 +1471,7 @@ msgstr "Erreur lors du chargement des différences :" #: lib/diff.tcl:303 msgid "Failed to unstage selected hunk." -msgstr "" -"La suppression dans le pré-commit de la section sélectionnée a échouée." +msgstr "La suppression dans le pré-commit de la section sélectionnée a échouée." #: lib/diff.tcl:310 msgid "Failed to stage selected hunk." @@ -1510,8 +1501,7 @@ msgstr "Erreur de pré-commit" msgid "" "Updating the Git index failed. A rescan will be automatically started to " "resynchronize git-gui." -msgstr "" -"Le pré-commit a échoué. Une resynchronisation va être lancée automatiquement." +msgstr "Le pré-commit a échoué. Une resynchronisation va être lancée automatiquement." #: lib/index.tcl:27 msgid "Continue" @@ -1527,9 +1517,8 @@ msgid "Unstaging %s from commit" msgstr "Supprimer %s du commit" #: lib/index.tcl:313 -#, fuzzy msgid "Ready to commit." -msgstr "Pré-commité" +msgstr "Prêt à être commité." #: lib/index.tcl:326 #, tcl-format @@ -1627,9 +1616,9 @@ msgid "%s of %s" msgstr "%s de %s" #: lib/merge.tcl:119 -#, fuzzy, tcl-format +#, tcl-format msgid "Merging %s and %s..." -msgstr "Fusion de %s et %s" +msgstr "Fusion de %s et %s..." #: lib/merge.tcl:130 msgid "Merge completed successfully." @@ -1693,9 +1682,8 @@ msgid "Aborting" msgstr "Abandon" #: lib/merge.tcl:238 -#, fuzzy msgid "files reset" -msgstr "fichiers" +msgstr "fichiers réinitialisés" #: lib/merge.tcl:265 msgid "Abort failed." @@ -1759,9 +1747,8 @@ msgid "Number of Diff Context Lines" msgstr "Nombre de lignes de contexte dans les diffs" #: lib/option.tcl:127 -#, fuzzy msgid "Commit Message Text Width" -msgstr "Message de commit :" +msgstr "Largeur du texte de message de commit" #: lib/option.tcl:128 msgid "New Branch Name Template" @@ -1769,7 +1756,7 @@ msgstr "Nouveau modèle de nom de branche" #: lib/option.tcl:192 msgid "Spelling Dictionary:" -msgstr "" +msgstr "Dictionnaire d'orthographe :" #: lib/option.tcl:216 msgid "Change Font" @@ -1898,40 +1885,40 @@ msgstr "Impossible d'écrire l'icône :" #: lib/spellcheck.tcl:57 msgid "Unsupported spell checker" -msgstr "" +msgstr "Vérificateur d'orthographe non supporté" #: lib/spellcheck.tcl:65 msgid "Spell checking is unavailable" -msgstr "" +msgstr "La vérification d'orthographe n'est pas disponible" #: lib/spellcheck.tcl:68 msgid "Invalid spell checking configuration" -msgstr "" +msgstr "Configuration de vérification d'orthographe invalide" #: lib/spellcheck.tcl:70 #, tcl-format msgid "Reverting dictionary to %s." -msgstr "" +msgstr "Réinitialisation du dictionnaire à %s." #: lib/spellcheck.tcl:73 msgid "Spell checker silently failed on startup" -msgstr "" +msgstr "La vérification d'orthographe a échouée silentieusement au démarrage" #: lib/spellcheck.tcl:80 msgid "Unrecognized spell checker" -msgstr "" +msgstr "Vérificateur d'orthographe non reconnu" #: lib/spellcheck.tcl:180 msgid "No Suggestions" -msgstr "" +msgstr "Aucune suggestion" #: lib/spellcheck.tcl:381 msgid "Unexpected EOF from spell checker" -msgstr "" +msgstr "Fin de fichier innatendue envoyée par le vérificateur d'orthographe" #: lib/spellcheck.tcl:385 msgid "Spell Checker Failed" -msgstr "" +msgstr "Le vérificateur d'orthographe a échoué" #: lib/status_bar.tcl:83 #, tcl-format @@ -2002,3 +1989,4 @@ msgstr "Utiliser des petits paquets (pour les connexions lentes)" #: lib/transport.tcl:168 msgid "Include tags" msgstr "Inclure les marques" + diff --git a/git-svn.perl b/git-svn.perl index 0c2b791eab..81afb5cfcd 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1900,7 +1900,7 @@ sub prop_walk { foreach (sort keys %$dirent) { next if $dirent->{$_}->{kind} != $SVN::Node::dir; - $self->prop_walk($path . '/' . $_, $rev, $sub); + $self->prop_walk($p . $_, $rev, $sub); } } @@ -2239,12 +2239,13 @@ sub find_parent_branch { # just grow a tail if we're not unique enough :x $ref_id .= '-' while find_ref($ref_id); print STDERR "Initializing parent: $ref_id\n"; - my ($u, $p) = ($new_url, ''); + my ($u, $p, $repo_id) = ($new_url, '', $ref_id); if ($u =~ s#^\Q$url\E(/|$)##) { $p = $u; $u = $url; + $repo_id = $self->{repo_id}; } - $gs = Git::SVN->init($u, $p, $self->{repo_id}, $ref_id, 1); + $gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1); } my ($r0, $parent) = $gs->find_rev_before($r, 1); if (!defined $r0 || !defined $parent) { @@ -148,8 +148,9 @@ static int handle_alias(int *argcp, const char ***argv) const char** new_argv; const char *alias_command; char *alias_string; + int unused_nongit; - subdir = setup_git_directory_gently(NULL); + subdir = setup_git_directory_gently(&unused_nongit); alias_command = (*argv)[0]; alias_string = alias_lookup(alias_command); diff --git a/gitk-git/gitk b/gitk-git/gitk index 84ab02e15f..9a4d9c40cf 100644 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -8045,11 +8045,11 @@ proc doprefs {} { grid $top.cdisp - -sticky w -pady 10 label $top.bg -padx 40 -relief sunk -background $bgcolor button $top.bgbut -text [mc "Background"] -font optionfont \ - -command [list choosecolor bgcolor 0 $top.bg background setbg] + -command [list choosecolor bgcolor {} $top.bg background setbg] grid x $top.bgbut $top.bg -sticky w label $top.fg -padx 40 -relief sunk -background $fgcolor button $top.fgbut -text [mc "Foreground"] -font optionfont \ - -command [list choosecolor fgcolor 0 $top.fg foreground setfg] + -command [list choosecolor fgcolor {} $top.fg foreground setfg] grid x $top.fgbut $top.fg -sticky w label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0] button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \ @@ -8069,7 +8069,7 @@ proc doprefs {} { grid x $top.hunksepbut $top.hunksep -sticky w label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor button $top.selbgbut -text [mc "Select bg"] -font optionfont \ - -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg] + -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg] grid x $top.selbgbut $top.selbgsep -sticky w label $top.cfont -text [mc "Fonts: press to choose"] diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ec73cb1256..73d098a433 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2164,7 +2164,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = $2; $res{'from_id'} = $3; $res{'to_id'} = $4; - $res{'status'} = $res{'status_str'} = $5; + $res{'status'} = $5; $res{'similarity'} = $6; if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); @@ -2180,7 +2180,6 @@ sub parse_difftree_raw_line { $res{'to_mode'} = pop @{$res{'from_mode'}}; $res{'from_id'} = [ split(' ', $3) ]; $res{'to_id'} = pop @{$res{'from_id'}}; - $res{'status_str'} = $4; $res{'status'} = [ split('', $4) ]; $res{'to_file'} = unquote($5); } @@ -3002,7 +3001,7 @@ sub fill_from_file_info { sub is_deleted { my $diffinfo = shift; - return $diffinfo->{'status_str'} =~ /D/; + return $diffinfo->{'to_id'} eq ('0' x 40); } # does patch correspond to [previous] difftree raw line @@ -30,6 +30,7 @@ static struct option builtin_help_options[] = { HELP_FORMAT_WEB), OPT_SET_INT('i', "info", &help_format, "show info page", HELP_FORMAT_INFO), + OPT_END(), }; static const char * const builtin_help_usage[] = { diff --git a/log-tree.c b/log-tree.c index 5b2963998c..9d54061601 100644 --- a/log-tree.c +++ b/log-tree.c @@ -317,8 +317,10 @@ void show_log(struct rev_info *opt, const char *sep) if (opt->show_log_size) printf("log size %i\n", (int)msgbuf.len); - if (msgbuf.len) - printf("%s%s%s", msgbuf.buf, extra, sep); + if (msgbuf.len) { + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + printf("%s%s", extra, sep); + } strbuf_release(&msgbuf); } @@ -8,10 +8,11 @@ * message and a signature block that git itself doesn't care about, * but that can be verified with gpg or similar. * - * The first three lines are guaranteed to be at least 63 bytes: + * The first four lines are guaranteed to be at least 83 bytes: * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the - * shortest possible type-line, and "tag .\n" at 6 bytes is the - * shortest single-character-tag line. + * shortest possible type-line, "tag .\n" at 6 bytes is the shortest + * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is + * the shortest possible tagger-line. */ /* @@ -43,9 +44,10 @@ static int verify_tag(char *buffer, unsigned long size) int typelen; char type[20]; unsigned char sha1[20]; - const char *object, *type_line, *tag_line, *tagger_line; + const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb; + size_t len; - if (size < 64) + if (size < 84) return error("wanna fool me ? you obviously got the size wrong !"); buffer[size] = 0; @@ -97,11 +99,51 @@ static int verify_tag(char *buffer, unsigned long size) /* Verify the tagger line */ tagger_line = tag_line; - if (memcmp(tagger_line, "tagger", 6) || (tagger_line[6] == '\n')) - return error("char" PD_FMT ": could not find \"tagger\"", tagger_line - buffer); - - /* TODO: check for committer info + blank line? */ - /* Also, the minimum length is probably + "tagger .", or 63+8=71 */ + if (memcmp(tagger_line, "tagger ", 7)) + return error("char" PD_FMT ": could not find \"tagger \"", + tagger_line - buffer); + + /* + * Check for correct form for name and email + * i.e. " <" followed by "> " on _this_ line + * No angle brackets within the name or email address fields. + * No spaces within the email address field. + */ + tagger_line += 7; + if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) || + strpbrk(tagger_line, "<>\n") != lb+1 || + strpbrk(lb+2, "><\n ") != rb) + return error("char" PD_FMT ": malformed tagger field", + tagger_line - buffer); + + /* Check for author name, at least one character, space is acceptable */ + if (lb == tagger_line) + return error("char" PD_FMT ": missing tagger name", + tagger_line - buffer); + + /* timestamp, 1 or more digits followed by space */ + tagger_line = rb + 2; + if (!(len = strspn(tagger_line, "0123456789"))) + return error("char" PD_FMT ": missing tag timestamp", + tagger_line - buffer); + tagger_line += len; + if (*tagger_line != ' ') + return error("char" PD_FMT ": malformed tag timestamp", + tagger_line - buffer); + tagger_line++; + + /* timezone, 5 digits [+-]hhmm, max. 1400 */ + if (!((tagger_line[0] == '+' || tagger_line[0] == '-') && + strspn(tagger_line+1, "0123456789") == 4 && + tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400)) + return error("char" PD_FMT ": malformed tag timezone", + tagger_line - buffer); + tagger_line += 6; + + /* Verify the blank line separating the header from the body */ + if (*tagger_line != '\n') + return error("char" PD_FMT ": trailing garbage in tag header", + tagger_line - buffer); /* The actual stuff afterwards we don't care about.. */ return 0; diff --git a/parse-options.c b/parse-options.c index 8e64316fe0..e87cafbe41 100644 --- a/parse-options.c +++ b/parse-options.c @@ -409,3 +409,10 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset) *(int *)(opt->value) = v; return 0; } + +int parse_opt_approxidate_cb(const struct option *opt, const char *arg, + int unset) +{ + *(unsigned long *)(opt->value) = approxidate(arg); + return 0; +} diff --git a/parse-options.h b/parse-options.h index 1af62b0485..4ee443dafe 100644 --- a/parse-options.h +++ b/parse-options.h @@ -94,6 +94,9 @@ struct option { #define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } #define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } #define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_DATE(s, l, v, h) \ + { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ + parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } @@ -110,6 +113,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr, /*----- some often used options -----*/ extern int parse_opt_abbrev_cb(const struct option *, const char *, int); +extern int parse_opt_approxidate_cb(const struct option *, const char *, int); #define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose") #define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet") @@ -457,6 +457,7 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, const struct commit *commit = c->commit; const char *msg = commit->buffer; struct commit_list *p; + int h1, h2; /* these are independent of the commit */ switch (placeholder[0]) { @@ -478,6 +479,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, case 'n': /* newline */ strbuf_addch(sb, '\n'); return 1; + case 'x': + /* %x00 == NUL, %x0a == LF, etc. */ + if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) && + h1 <= 16 && + 0 <= (h2 = hexval_table[0xff & placeholder[2]]) && + h2 <= 16) { + strbuf_addch(sb, (h1<<4)|h2); + return 3; + } else + return 0; } /* these depend on the commit */ diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh new file mode 100755 index 0000000000..e15e3eb81b --- /dev/null +++ b/t/t2201-add-update-typechange.sh @@ -0,0 +1,140 @@ +#!/bin/sh + +test_description='more git add -u' + +. ./test-lib.sh + +_z40=0000000000000000000000000000000000000000 + +test_expect_success setup ' + >xyzzy && + _empty=$(git hash-object --stdin <xyzzy) && + >yomin && + >caskly && + ln -s frotz nitfol && + mkdir rezrov && + >rezrov/bozbar && + git add caskly xyzzy yomin nitfol rezrov/bozbar && + + test_tick && + git commit -m initial + +' + +test_expect_success modify ' + rm -f xyzzy yomin nitfol caskly && + # caskly disappears (not a submodule) + mkdir caskly && + # nitfol changes from symlink to regular + >nitfol && + # rezrov/bozbar disappears + rm -fr rezrov && + ln -s xyzzy rezrov && + # xyzzy disappears (not a submodule) + mkdir xyzzy && + echo gnusto >xyzzy/bozbar && + # yomin gets replaced with a submodule + mkdir yomin && + >yomin/yomin && + ( + cd yomin && + git init && + git add yomin && + git commit -m "sub initial" + ) && + yomin=$(GIT_DIR=yomin/.git git rev-parse HEAD) && + # yonk is added and then turned into a submodule + # this should appear as T in diff-files and as A in diff-index + >yonk && + git add yonk && + rm -f yonk && + mkdir yonk && + >yonk/yonk && + ( + cd yonk && + git init && + git add yonk && + git commit -m "sub initial" + ) && + yonk=$(GIT_DIR=yonk/.git git rev-parse HEAD) && + # zifmia is added and then removed + # this should appear in diff-files but not in diff-index. + >zifmia && + git add zifmia && + rm -f zifmia && + mkdir zifmia && + { + git ls-tree -r HEAD | + sed -e "s/^/:/" -e " + / caskly/{ + s/ caskly/ $_z40 D&/ + s/blob/000000/ + } + / nitfol/{ + s/ nitfol/ $_z40 T&/ + s/blob/100644/ + } + / rezrov.bozbar/{ + s/ rezrov.bozbar/ $_z40 D&/ + s/blob/000000/ + } + / xyzzy/{ + s/ xyzzy/ $_z40 D&/ + s/blob/000000/ + } + / yomin/{ + s/ yomin/ $_z40 T&/ + s/blob/160000/ + } + " + } >expect && + { + cat expect + echo ":100644 160000 $_empty $_z40 T yonk" + echo ":100644 000000 $_empty $_z40 D zifmia" + } >expect-files && + { + cat expect + echo ":000000 160000 $_z40 $_z40 A yonk" + } >expect-index && + { + echo "100644 $_empty 0 nitfol" + echo "160000 $yomin 0 yomin" + echo "160000 $yonk 0 yonk" + } >expect-final +' + +test_expect_success diff-files ' + git diff-files --raw >actual && + diff -u expect-files actual +' + +test_expect_success diff-index ' + git diff-index --raw HEAD -- >actual && + diff -u expect-index actual +' + +test_expect_success 'add -u' ' + rm -f ".git/saved-index" && + cp -p ".git/index" ".git/saved-index" && + git add -u && + git ls-files -s >actual && + diff -u expect-final actual +' + +test_expect_success 'commit -a' ' + if test -f ".git/saved-index" + then + rm -f ".git/index" && + mv ".git/saved-index" ".git/index" + fi && + git commit -m "second" -a && + git ls-files -s >actual && + diff -u expect-final actual && + rm -f .git/index && + git read-tree HEAD && + git ls-files -s >actual && + diff -u expect-final actual +' + +test_done diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index bdc6e132ca..df1fd6f86f 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -44,6 +44,8 @@ cat >tag.sig <<EOF xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895 type tag tag mytag +tagger . <> 0 +0000 + EOF check_verify_failure '"object" line label check' '^error: char0: .*"object "$' @@ -55,6 +57,8 @@ cat >tag.sig <<EOF object zz9e9b33986b1c2670fff52c5067603117b3e895 type tag tag mytag +tagger . <> 0 +0000 + EOF check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$' @@ -66,6 +70,8 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 xxxx tag tag mytag +tagger . <> 0 +0000 + EOF check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$' @@ -85,6 +91,8 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 type tag xxx mytag +tagger . <> 0 +0000 + EOF check_verify_failure '"tag" line label check #1' \ @@ -121,6 +129,8 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 type tagggg tag mytag +tagger . <> 0 +0000 + EOF check_verify_failure 'verify object (SHA1/type) check' \ @@ -133,6 +143,8 @@ cat >tag.sig <<EOF object $head type commit tag my tag +tagger . <> 0 +0000 + EOF check_verify_failure 'verify tag-name check' \ @@ -145,10 +157,12 @@ cat >tag.sig <<EOF object $head type commit tag mytag + +This is filler EOF check_verify_failure '"tagger" line label check #1' \ - '^error: char70: could not find "tagger"$' + '^error: char70: could not find "tagger "$' ############################################################ # 12. tagger line label check #2 @@ -158,19 +172,180 @@ object $head type commit tag mytag tagger + +This is filler EOF check_verify_failure '"tagger" line label check #2' \ - '^error: char70: could not find "tagger"$' + '^error: char70: could not find "tagger "$' ############################################################ -# 13. create valid tag +# 13. disallow missing tag author name cat >tag.sig <<EOF object $head type commit tag mytag -tagger another@example.com +tagger <> 0 +0000 + +This is filler +EOF + +check_verify_failure 'disallow missing tag author name' \ + '^error: char77: missing tagger name$' + +############################################################ +# 14. disallow missing tag author name + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger < + > 0 +0000 + +EOF + +check_verify_failure 'disallow malformed tagger' \ + '^error: char77: malformed tagger field$' + +############################################################ +# 15. allow empty tag email + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <> 0 +0000 + +EOF + +test_expect_success \ + 'allow empty tag email' \ + 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message' + +############################################################ +# 16. disallow spaces in tag email + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tag ger@example.com> 0 +0000 + +EOF + +check_verify_failure 'disallow spaces in tag email' \ + '^error: char77: malformed tagger field$' + +############################################################ +# 17. disallow missing tag timestamp + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> + +EOF + +check_verify_failure 'disallow missing tag timestamp' \ + '^error: char107: missing tag timestamp$' + +############################################################ +# 18. detect invalid tag timestamp1 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008 + +EOF + +check_verify_failure 'detect invalid tag timestamp1' \ + '^error: char107: missing tag timestamp$' + +############################################################ +# 19. detect invalid tag timestamp2 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500 + +EOF + +check_verify_failure 'detect invalid tag timestamp2' \ + '^error: char111: malformed tag timestamp$' + +############################################################ +# 20. detect invalid tag timezone1 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 GMT + +EOF + +check_verify_failure 'detect invalid tag timezone1' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 21. detect invalid tag timezone2 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 + 30 + +EOF + +check_verify_failure 'detect invalid tag timezone2' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 22. detect invalid tag timezone3 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -1430 + +EOF + +check_verify_failure 'detect invalid tag timezone3' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 23. detect invalid header entry + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -0500 +this line should not be here + +EOF + +check_verify_failure 'detect invalid header entry' \ + '^error: char124: trailing garbage in tag header$' + +############################################################ +# 24. create valid tag + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -0500 + EOF test_expect_success \ @@ -178,7 +353,7 @@ test_expect_success \ 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message' ############################################################ -# 14. check mytag +# 25. check mytag test_expect_success \ 'check mytag' \ diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh index 64f34e3298..43943ab8ca 100755 --- a/t/t4104-apply-boundary.sh +++ b/t/t4104-apply-boundary.sh @@ -112,4 +112,17 @@ do ' done +test_expect_success 'two lines' ' + + >file && + git add file && + echo aaa >file && + git diff >patch && + git add file && + echo bbb >file && + git add file && + test_must_fail git apply --check patch + +' + test_done diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index 47090c4cf5..9fd9d07000 100644 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -78,4 +78,38 @@ test_expect_success 'gc: start with ok gc.pruneExpire' ' ' +test_expect_success 'prune: prune nonsense parameters' ' + + test_must_fail git prune garbage && + test_must_fail git prune --- && + test_must_fail git prune --no-such-option + +' + +test_expect_success 'prune: prune unreachable heads' ' + + git config core.logAllRefUpdates false && + mv .git/logs .git/logs.old && + : > file2 && + git add file2 && + git commit -m temporary && + tmp_head=$(git rev-list -1 HEAD) && + git reset HEAD^ && + git prune && + test_must_fail git reset $tmp_head -- + +' + +test_expect_success 'prune: do not prune heads listed as an argument' ' + + : > file2 && + git add file2 && + git commit -m temporary && + tmp_head=$(git rev-list -1 HEAD) && + git reset HEAD^ && + git prune -- $tmp_head && + git reset $tmp_head -- + +' + test_done diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 6827249da5..efd658adb6 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -17,6 +17,8 @@ test_expect_success 'setup' ' make_commit B git checkout -b branch B make_commit D + mkdir dir + make_commit dir/D make_commit E git checkout master make_commit C @@ -41,9 +43,23 @@ test_expect_success 'rewrite, renaming a specific file' ' ' test_expect_success 'test that the file was renamed' ' - test d = $(git show HEAD:doh) && + test d = "$(git show HEAD:doh --)" && + ! test -f d && test -f doh && - test d = $(cat doh) + test d = "$(cat doh)" +' + +test_expect_success 'rewrite, renaming a specific directory' ' + git-filter-branch -f --tree-filter "mv dir diroh || :" HEAD +' + +test_expect_success 'test that the directory was renamed' ' + test dir/d = "$(git show HEAD:diroh/d --)" && + ! test -d dir && + test -d diroh && + ! test -d diroh/dir && + test -f diroh/d && + test dir/d = "$(cat diroh/d)" ' git tag oldD HEAD~4 diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 75cd33bde8..1a7141ecd7 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -578,6 +578,14 @@ test_expect_success \ git diff expect actual ' +# subsequent tests require gpg; check if it is available +gpg --version >/dev/null +if [ $? -eq 127 ]; then + echo "gpg not found - skipping tag signing and verification tests" + test_done + exit +fi + # trying to verify annotated non-signed tags: test_expect_success \ @@ -600,13 +608,6 @@ test_expect_success \ # creating and verifying signed tags: -gpg --version >/dev/null -if [ $? -eq 127 ]; then - echo "Skipping signed tags tests, because gpg was not found" - test_done - exit -fi - # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 # the gpg version 1.0.6 didn't parse trust packets correctly, so for # that version, creation of signed tags using the generated key fails. diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 6a74b3acfd..2d919d69ef 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -4,8 +4,6 @@ test_description='GIT_EDITOR, core.editor, and stuff' . ./test-lib.sh -OLD_TERM="$TERM" - for i in GIT_EDITOR core_editor EDITOR VISUAL vi do cat >e-$i.sh <<-EOF @@ -116,6 +114,4 @@ test_expect_success 'core.editor with a space' ' ' -TERM="$OLD_TERM" - test_done diff --git a/t/t9121-git-svn-fetch-renamed-dir.sh b/t/t9121-git-svn-fetch-renamed-dir.sh new file mode 100755 index 0000000000..5143ed6066 --- /dev/null +++ b/t/t9121-git-svn-fetch-renamed-dir.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Copyright (c) 2008 Santhosh Kumar Mani + + +test_description='git-svn can fetch renamed directories' + +. ./lib-git-svn.sh + +test_expect_success 'load repository with renamed directory' " + svnadmin load -q $rawsvnrepo < ../t9121/renamed-dir.dump + " + +test_expect_success 'init and fetch repository' " + git svn init $svnrepo/newname && + git svn fetch + " + +test_done + diff --git a/t/t9121/renamed-dir.dump b/t/t9121/renamed-dir.dump new file mode 100644 index 0000000000..5f9127be92 --- /dev/null +++ b/t/t9121/renamed-dir.dump @@ -0,0 +1,90 @@ +SVN-fs-dump-format-version: 2 + +UUID: 06b9b3ad-f546-4fbe-8328-fcb4e6ef5c3f + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-04-02T09:11:59.778557Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 14 +initial import +K 10 +svn:author +V 8 +santhosh +K 8 +svn:date +V 27 +2008-04-02T09:13:03.170863Z +PROPS-END + +Node-path: name +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: name/a.txt +Node-kind: file +Node-action: add +Prop-content-length: 71 +Text-content-length: 6 +Text-content-md5: b1946ac92492d2347c6235b4d2611184 +Content-length: 77 + +K 13 +svn:mime-type +V 10 +text/plain +K 13 +svn:eol-style +V 2 +LF +PROPS-END +hello + + +Revision-number: 2 +Prop-content-length: 109 +Content-length: 109 + +K 7 +svn:log +V 7 +renamed +K 10 +svn:author +V 8 +santhosh +K 8 +svn:date +V 27 +2008-04-02T09:14:22.952186Z +PROPS-END + +Node-path: newname +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: name + + +Node-path: name +Node-action: delete + + diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index b91b151417..166b43f783 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -420,4 +420,54 @@ test_expect_success 'cvs update (merge no-op)' \ GIT_CONFIG="$git_config" cvs -Q update && diff -q merge ../merge' +cd "$WORKDIR" +test_expect_success 'cvs update (-p)' ' + touch really-empty && + echo Line 1 > no-lf && + echo -n Line 2 >> no-lf && + git add really-empty no-lf && + git commit -q -m "Update -p test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + rm -f failures && + for i in merge no-lf empty really-empty; do + GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out + diff $i.out ../$i >>failures 2>&1 + done && + test -z "$(cat failures)" +' + +#------------ +# CVS STATUS +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs status' ' + mkdir status.dir && + echo Line > status.dir/status.file && + echo Line > status.file && + git add status.dir status.file && + git commit -q -m "Status test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out && + test $(wc -l <../out) = 2 +' + +cd "$WORKDIR" +test_expect_success 'cvs status (nonrecursive)' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out && + test $(wc -l <../out) = 1 +' + +cd "$WORKDIR" +test_expect_success 'cvs status (no subdirs in header)' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs status | grep ^File: >../out && + ! grep / <../out +' + test_done |