diff options
-rw-r--r-- | Documentation/RelNotes-1.5.3.txt | 16 | ||||
-rw-r--r-- | Documentation/asciidoc.conf | 6 | ||||
-rw-r--r-- | Documentation/git-branch.txt | 4 | ||||
-rw-r--r-- | Documentation/git-stash.txt | 11 | ||||
-rw-r--r-- | INSTALL | 7 | ||||
-rw-r--r-- | Makefile | 26 | ||||
-rw-r--r-- | builtin-mailinfo.c | 33 | ||||
-rw-r--r-- | contrib/emacs/Makefile | 2 | ||||
-rw-r--r-- | contrib/p4import/README | 1 | ||||
-rw-r--r-- | contrib/p4import/git-p4import.py (renamed from git-p4import.py) | 0 | ||||
-rw-r--r-- | contrib/p4import/git-p4import.txt (renamed from Documentation/git-p4import.txt) | 0 | ||||
-rw-r--r-- | entry.c | 37 | ||||
-rwxr-xr-x | git-filter-branch.sh | 31 | ||||
-rwxr-xr-x | git-svn.perl | 5 | ||||
-rw-r--r-- | git.spec.in | 29 | ||||
-rw-r--r-- | t/lib-git-svn.sh | 34 | ||||
-rwxr-xr-x | t/t7400-submodule-basic.sh | 9 | ||||
-rwxr-xr-x | t/t9115-git-svn-dcommit-funky-renames.sh | 54 | ||||
-rw-r--r-- | t/t9115/funky-names.dump | 103 | ||||
-rw-r--r-- | unpack-trees.c | 75 |
20 files changed, 374 insertions, 109 deletions
diff --git a/Documentation/RelNotes-1.5.3.txt b/Documentation/RelNotes-1.5.3.txt index 63e33b9..896ff1d 100644 --- a/Documentation/RelNotes-1.5.3.txt +++ b/Documentation/RelNotes-1.5.3.txt @@ -21,6 +21,8 @@ Updates since v1.5.2 * New commands and options. + - "git log --date=<format>" can use more formats: iso8601, rfc2822. + - The hunk header output from "git diff" family can be customized with the attributes mechanism. See gitattributes(5) for details. @@ -68,6 +70,10 @@ Updates since v1.5.2 - "git gc --aggressive" tells the command to spend more cycles to optimize the repository harder. + - "git repack" learned a "window-memory" limit which + dynamically reduces the window size to stay within the + specified memory usage. + - "git repack" can be told to split resulting packs to avoid exceeding limit specified with "--max-pack-size". @@ -99,6 +105,9 @@ Updates since v1.5.2 * Updated behavior of existing commands. + - "git rm --cached" does not complain when removing a newly + added file from the index anymore. + - "git svn dcommit" retains local merge information. - "git config" to set values also honors type flags like --bool @@ -175,6 +184,11 @@ Updates since v1.5.2 concatenate them into a single line and treat the result as "oneline". + - "git p4import" has been demoted to contrib status. For + a superior option, checkout the git-p4 front end to + git-fast-import (also in contrib). The man page and p4 + rpm have been removed as well. + * Builds - old-style function definitions (most notably, a function @@ -218,6 +232,6 @@ this release, unless otherwise noted. -- exec >/var/tmp/1 -O=v1.5.3-rc1 +O=v1.5.3-rc2 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 6b6220d..af5b155 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -27,7 +27,13 @@ ifdef::backend-docbook[] [listingblock] <example><title>{title}</title> <literallayout> +ifdef::doctype-manpage[] + .ft C +endif::doctype-manpage[] | +ifdef::doctype-manpage[] + .ft +endif::doctype-manpage[] </literallayout> {title#}</example> endif::backend-docbook[] diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bb6b57d..bc6aa88 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -130,8 +130,8 @@ Delete unneeded branch:: ------------ $ git clone git://git.kernel.org/.../git.git my.git $ cd my.git -$ git branch -d -r todo html man <1> -$ git branch -D test <2> +$ git branch -d -r origin/todo origin/html origin/man <1> +$ git branch -D test <2> ------------ + <1> delete remote-tracking branches "todo", "html", "man" diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt index ad95ed9..17121ad 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.txt @@ -8,7 +8,8 @@ git-stash - Stash the changes in a dirty working directory away SYNOPSIS -------- [verse] -'git-stash' (save | list | show [<stash>] | apply [<stash>] | clear) +'git-stash' (list | show [<stash>] | apply [<stash>] | clear) +'git-stash' [save] [message...] DESCRIPTION ----------- @@ -22,7 +23,9 @@ The modifications stashed away by this command can be listed with `git-stash list`, inspected with `git-stash show`, and restored (potentially on top of a different commit) with `git-stash apply`. Calling git-stash without any arguments is equivalent to `git-stash -save`. +save`. A stash is by default listed as "WIP on 'branchname' ...", but +you can give a more descriptive message on the command line when +you create one. The latest stash you created is stored in `$GIT_DIR/refs/stash`; older stashes are found in the reflog of this reference and can be named using @@ -48,8 +51,8 @@ list:: based on. + ---------------------------------------------------------------- -stash@{0}: submit: 6ebd0e2... Add git-stash -stash@{1}: master: 9cc0589... Merge branch 'master' of gfi +stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation +stash@{1}: On master: 9cc0589... Add git-stash ---------------------------------------------------------------- show [<stash>]:: @@ -56,9 +56,8 @@ Issues of note: - "zlib", the compression library. Git won't build without it. - - "openssl". The git-rev-list program uses bignum support from - openssl, and unless you specify otherwise, you'll also get the - SHA1 library from here. + - "openssl". Unless you specify otherwise, you'll get the SHA1 + library from here. If you don't have openssl, you can use one of the SHA1 libraries that come with git (git includes the one from Mozilla, and has @@ -73,7 +72,7 @@ Issues of note: management over DAV. Similar to "curl" above, this is optional. - "wish", the Tcl/Tk windowing shell is used in gitk to show the - history graphically + history graphically, and in git-gui. - "ssh" is used to push and pull over the net @@ -112,8 +112,6 @@ all:: # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's # MakeMaker (e.g. using ActiveState under Cygwin). # -# Define WITH_P4IMPORT to build and install Python git-p4import script. -# # Define NO_TCLTK if you do not want Tcl/Tk GUI. # # The TCL_PATH variable governs the location of the Tcl interpreter @@ -223,20 +221,9 @@ SCRIPT_PERL = \ git-svnimport.perl git-cvsexportcommit.perl \ git-send-email.perl git-svn.perl -SCRIPT_PYTHON = \ - git-p4import.py - -ifdef WITH_P4IMPORT SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ - $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ git-status git-instaweb -else -SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ - $(patsubst %.perl,%,$(SCRIPT_PERL)) \ - git-status git-instaweb -endif - # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS = \ @@ -286,9 +273,6 @@ endif ifndef PERL_PATH PERL_PATH = /usr/bin/perl endif -ifndef PYTHON_PATH - PYTHON_PATH = /usr/local/bin/python -endif export PERL_PATH @@ -711,7 +695,6 @@ prefix_SQ = $(subst ','\'',$(prefix)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) -PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH)) TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) LIBS = $(GITLIBS) $(EXTLIBS) @@ -782,15 +765,6 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak -$(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py - $(RM) $@ $@+ - sed -e '1s|#!.*/python|#!$(PYTHON_PATH_SQ)|' \ - -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ - -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ - $@.py >$@+ - chmod +x $@+ - mv $@+ $@ - perl/perl.mak: GIT-CFLAGS $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 489c2c5..a37a4ff 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -499,15 +499,40 @@ static int decode_b_segment(char *in, char *ot, char *ep) return 0; } +/* + * When there is no known charset, guess. + * + * Right now we assume that if the target is UTF-8 (the default), + * and it already looks like UTF-8 (which includes US-ASCII as its + * subset, of course) then that is what it is and there is nothing + * to do. + * + * Otherwise, we default to assuming it is Latin1 for historical + * reasons. + */ +static const char *guess_charset(const char *line, const char *target_charset) +{ + if (is_encoding_utf8(target_charset)) { + if (is_utf8(line)) + return NULL; + } + return "latin1"; +} + static void convert_to_utf8(char *line, const char *charset) { - static const char latin_one[] = "latin1"; - const char *input_charset = *charset ? charset : latin_one; - char *out = reencode_string(line, metainfo_charset, input_charset); + char *out; + + if (!charset || !*charset) { + charset = guess_charset(line, metainfo_charset); + if (!charset) + return; + } + out = reencode_string(line, metainfo_charset, charset); if (!out) die("cannot convert from %s to %s\n", - input_charset, metainfo_charset); + charset, metainfo_charset); strcpy(line, out); free(out); } diff --git a/contrib/emacs/Makefile b/contrib/emacs/Makefile index 5e94d6f..a48540a 100644 --- a/contrib/emacs/Makefile +++ b/contrib/emacs/Makefile @@ -13,7 +13,7 @@ all: $(ELC) install: all $(INSTALL) -d $(DESTDIR)$(emacsdir) - $(INSTALL_ELC) $(ELC) $(DESTDIR)$(emacsdir) + $(INSTALL_ELC) $(ELC:.elc=.el) $(ELC) $(DESTDIR)$(emacsdir) %.elc: %.el $(EMACS) -batch -f batch-byte-compile $< diff --git a/contrib/p4import/README b/contrib/p4import/README new file mode 100644 index 0000000..b9892b6 --- /dev/null +++ b/contrib/p4import/README @@ -0,0 +1 @@ +Please see contrib/fast-import/git-p4 for a better Perforce importer. diff --git a/git-p4import.py b/contrib/p4import/git-p4import.py index 0f3d97b..0f3d97b 100644 --- a/git-p4import.py +++ b/contrib/p4import/git-p4import.py diff --git a/Documentation/git-p4import.txt b/contrib/p4import/git-p4import.txt index 9967587..9967587 100644 --- a/Documentation/git-p4import.txt +++ b/contrib/p4import/git-p4import.txt @@ -8,17 +8,40 @@ static void create_directories(const char *path, const struct checkout *state) const char *slash = path; while ((slash = strchr(slash+1, '/')) != NULL) { + struct stat st; + int stat_status; + len = slash - path; memcpy(buf, path, len); buf[len] = 0; + + if (len <= state->base_dir_len) + /* + * checkout-index --prefix=<dir>; <dir> is + * allowed to be a symlink to an existing + * directory. + */ + stat_status = stat(buf, &st); + else + /* + * if there currently is a symlink, we would + * want to replace it with a real directory. + */ + stat_status = lstat(buf, &st); + + if (!stat_status && S_ISDIR(st.st_mode)) + continue; /* ok, it is already a directory. */ + + /* + * We know stat_status == 0 means something exists + * there and this mkdir would fail, but that is an + * error codepath; we do not care, as we unlink and + * mkdir again in such a case. + */ if (mkdir(buf, 0777)) { - if (errno == EEXIST) { - struct stat st; - if (len > state->base_dir_len && state->force && !unlink(buf) && !mkdir(buf, 0777)) - continue; - if (!stat(buf, &st) && S_ISDIR(st.st_mode)) - continue; /* ok */ - } + if (errno == EEXIST && state->force && + !unlink(buf) && !mkdir(buf, 0777)) + continue; die("cannot create directory at %s", buf); } } diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 5401970..0d000ed 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -8,8 +8,6 @@ # a new branch. You can specify a number of filters to modify the commits, # files and trees. -set -e - USAGE="git-filter-branch [-d TEMPDIR] [FILTERS] DESTBRANCH [REV-RANGE]" . git-sh-setup @@ -141,9 +139,10 @@ git show-ref "refs/heads/$dstbranch" 2> /dev/null && die "branch $dstbranch already exists" test ! -e "$tempdir" || die "$tempdir already exists, please remove it" -mkdir -p "$tempdir/t" -cd "$tempdir/t" -workdir="$(pwd)" +mkdir -p "$tempdir/t" && +cd "$tempdir/t" && +workdir="$(pwd)" || +die "" case "$GIT_DIR" in /*) @@ -155,12 +154,12 @@ esac export GIT_DIR GIT_WORK_TREE=. export GIT_INDEX_FILE="$(pwd)/../index" -git read-tree # seed the index file +git read-tree || die "Could not seed the index" ret=0 - -mkdir ../map # map old->new commit ids for rewriting parents +# map old->new commit ids for rewriting parents +mkdir ../map || die "Could not create map/ directory" case "$filter_subdir" in "") @@ -170,7 +169,7 @@ case "$filter_subdir" in *) git rev-list --reverse --topo-order --default HEAD \ --parents --full-history "$@" -- "$filter_subdir" -esac > ../revs +esac > ../revs || die "Could not get the commits" commits=$(wc -l <../revs | tr -d " ") test $commits -eq 0 && die "Found nothing to rewrite" @@ -186,10 +185,11 @@ while read commit parents; do ;; *) git read-tree -i -m $commit:"$filter_subdir" - esac + esac || die "Could not initialize the index" export GIT_COMMIT=$commit - git cat-file commit "$commit" >../commit + git cat-file commit "$commit" >../commit || + die "Cannot read commit $commit" eval "$(set_ident AUTHOR <../commit)" || die "setting author failed for commit $commit" @@ -199,7 +199,8 @@ while read commit parents; do die "env filter failed: $filter_env" if [ "$filter_tree" ]; then - git checkout-index -f -u -a + git checkout-index -f -u -a || + 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 ls-files -z --others | xargs -0 rm -f @@ -240,7 +241,8 @@ case "$target_head" in echo Nothing rewritten ;; *) - git update-ref refs/heads/"$dstbranch" $target_head + git update-ref refs/heads/"$dstbranch" $target_head || + die "Could not update $dstbranch with $target_head" if [ $(wc -l <../map/$src_head) -gt 1 ]; then echo "WARNING: Your commit filter caused the head commit to expand to several rewritten commits. Only the first such commit was recorded as the current $dstbranch head but you will need to resolve the situation now (probably by manually merging the other commits). These are all the commits:" >&2 sed 's/^/ /' ../map/$src_head >&2 @@ -277,7 +279,8 @@ if [ "$filter_tag_name" ]; then warn "unreferencing tag object $sha1t" fi - git update-ref "refs/tags/$new_ref" "$new_sha1" + git update-ref "refs/tags/$new_ref" "$new_sha1" || + die "Could not write tag $new_ref" done fi diff --git a/git-svn.perl b/git-svn.perl index 299b40f..6c692a7 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -740,7 +740,7 @@ sub load_authors { my $log = $cmd eq 'log'; while (<$authors>) { chomp; - next unless /^(\S+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/; + next unless /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/; my ($user, $name, $email) = ($1, $2, $3); if ($log) { $Git::SVN::Log::rusers{"$name <$email>"} = $user; @@ -2724,6 +2724,9 @@ sub repo_path { sub url_path { my ($self, $path) = @_; + if ($self->{url} =~ m#^https?://#) { + $path =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg; + } $self->{url} . '/' . $self->repo_path($path); } diff --git a/git.spec.in b/git.spec.in index 27182ba..fe7b3d8 100644 --- a/git.spec.in +++ b/git.spec.in @@ -12,7 +12,7 @@ URL: http://kernel.org/pub/software/scm/git/ Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3} BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Requires: git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, git-p4, perl-Git +Requires: git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, perl-Git %description Git is a fast, scalable, distributed revision control system with an @@ -53,13 +53,6 @@ Requires: git-core = %{version}-%{release}, tla %description arch Git tools for importing Arch repositories. -%package p4 -Summary: Git tools for importing Perforce repositories -Group: Development/Tools -Requires: git-core = %{version}-%{release}, python -%description p4 -Git tools for importing Perforce repositories. - %package email Summary: Git tools for sending email Group: Development/Tools @@ -95,14 +88,14 @@ Perl interface to Git %setup -q %build -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_P4IMPORT=YesPlease \ +make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" \ ETC_GITCONFIG=/etc/gitconfig \ - prefix=%{_prefix} PYTHON_PATH=%{python_path} all %{!?_without_docs: doc} + prefix=%{_prefix} all %{!?_without_docs: doc} %install rm -rf $RPM_BUILD_ROOT make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \ - WITH_P4IMPORT=YesPlease prefix=%{_prefix} mandir=%{_mandir} \ + prefix=%{_prefix} mandir=%{_mandir} \ ETC_GITCONFIG=/etc/gitconfig \ PYTHON_PATH=%{python_path} \ INSTALLDIRS=vendor install %{!?_without_docs: install-doc} @@ -110,10 +103,10 @@ find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';' find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';' find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';' -(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "p4import|archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files +(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files %if %{!?_without_docs:1}0 -(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "p4import|archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files +(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files %else rm -rf $RPM_BUILD_ROOT%{_mandir} %endif @@ -145,13 +138,6 @@ rm -rf $RPM_BUILD_ROOT %{!?_without_docs: %{_mandir}/man1/git-archimport.1*} %{!?_without_docs: %doc Documentation/git-archimport.html } -%files p4 -%defattr(-,root,root) -%doc Documentation/git-p4import.txt -%{_bindir}/git-p4import -%{!?_without_docs: %{_mandir}/man1/git-p4import.1*} -%{!?_without_docs: %doc Documentation/git-p4import.html } - %files email %defattr(-,root,root) %doc Documentation/*email*.txt @@ -187,6 +173,9 @@ rm -rf $RPM_BUILD_ROOT %{!?_without_docs: %doc Documentation/technical} %changelog +* Sun Jul 15 2007 Sean Estabrooks <seanlkml@sympatico.ca> +- Removed p4import. + * Tue Jun 26 2007 Quy Tonthat <qtonthat@gmail.com> - Fixed problems looking for wrong manpages. diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index f6fe78c..8d4a447 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -48,3 +48,37 @@ svnrepo="file://$svnrepo" poke() { test-chmtime +1 "$1" } + +SVN_HTTPD_MODULE_PATH=${SVN_HTTPD_MODULE_PATH-'/usr/lib/apache2/modules'} +SVN_HTTPD_PATH=${SVN_HTTPD_PATH-'/usr/sbin/apache2'} + +start_httpd () { + if test -z "$SVN_HTTPD_PORT" + then + echo >&2 'SVN_HTTPD_PORT is not defined!' + return + fi + + mkdir "$GIT_DIR"/logs + + cat > "$GIT_DIR/httpd.conf" <<EOF +ServerName "git-svn test" +ServerRoot "$GIT_DIR" +DocumentRoot "$GIT_DIR" +PidFile "$GIT_DIR/httpd.pid" +Listen 127.0.0.1:$SVN_HTTPD_PORT +LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so +LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so +<Location /svn> + DAV svn + SVNPath $rawsvnrepo +</Location> +EOF + "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start + svnrepo=http://127.0.0.1:$SVN_HTTPD_PORT/svn +} + +stop_httpd () { + test -z "$SVN_HTTPD_PORT" && return + "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k stop +} diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 5e91db6..e8ce7cd 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -21,6 +21,10 @@ subcommands of git-submodule. # -add an entry to .gitmodules for submodule 'example' # test_expect_success 'Prepare submodule testing' ' + : > t && + git-add t && + git-commit -m "initial commit" && + git branch initial HEAD && mkdir lib && cd lib && git init && @@ -166,4 +170,9 @@ test_expect_success 'status should be "up-to-date" after update' ' git-submodule status | grep "^ $rev1" ' +test_expect_success 'checkout superproject with subproject already present' ' + git-checkout initial && + git-checkout master +' + test_done diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh new file mode 100755 index 0000000..182299c --- /dev/null +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong + + +test_description='git-svn dcommit can commit renames of files with ugly names' + +. ./lib-git-svn.sh + +test_expect_success 'load repository with strange names' " + svnadmin load -q $rawsvnrepo < ../t9115/funky-names.dump && + start_httpd + " + +test_expect_success 'init and fetch repository' " + git svn init $svnrepo && + git svn fetch && + git reset --hard git-svn + " + +test_expect_success 'create file in existing ugly and empty dir' ' + mkdir "#{bad_directory_name}" && + echo hi > "#{bad_directory_name}/ foo" && + git update-index --add "#{bad_directory_name}/ foo" && + git commit -m "new file in ugly parent" && + git svn dcommit + ' + +test_expect_success 'rename ugly file' ' + git mv "#{bad_directory_name}/ foo" "file name with feces" && + git commit -m "rename ugly file" && + git svn dcommit + ' + +test_expect_success 'rename pretty file' ' + echo :x > pretty && + git update-index --add pretty && + git commit -m "pretty :x" && + git svn dcommit && + mkdir regular_dir_name && + git mv pretty regular_dir_name/pretty && + git commit -m "moved pretty file" && + git svn dcommit + ' + +test_expect_success 'rename pretty file into ugly one' ' + git mv regular_dir_name/pretty "#{bad_directory_name}/ booboo" && + git commit -m booboo && + git svn dcommit + ' + +stop_httpd + +test_done diff --git a/t/t9115/funky-names.dump b/t/t9115/funky-names.dump new file mode 100644 index 0000000..42422f7 --- /dev/null +++ b/t/t9115/funky-names.dump @@ -0,0 +1,103 @@ +SVN-fs-dump-format-version: 2 + +UUID: 819c44fe-2bcc-4066-88e4-985e2bc0b418 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2007-07-12T07:54:26.062914Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 152 +Content-length: 152 + +K 7 +svn:log +V 44 +what will those wacky people think of next? + +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2007-07-12T08:00:05.011573Z +PROPS-END + +Node-path: leading space +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: leading space file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 5 +Text-content-md5: e4fa20c67542cdc21271e08d329397ab +Content-length: 15 + +PROPS-END +ugly + + +Node-path: #{bad_directory_name} +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: #{cool_name} +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 18 +Text-content-md5: 87dac40ca337dfa3dcc8911388c3ddda +Content-length: 28 + +PROPS-END +strange name here + + +Node-path: dir name with spaces +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: file name with spaces +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 7 +Text-content-md5: c1f10cfd640618484a2a475c11410fd3 +Content-length: 17 + +PROPS-END +spaces + + +Node-path: regular_dir_name +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END diff --git a/unpack-trees.c b/unpack-trees.c index 89dd279..7cc029e 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -5,6 +5,7 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "progress.h" +#include "refs.h" #define DBRT_DEBUG 1 @@ -425,11 +426,24 @@ static void invalidate_ce_path(struct cache_entry *ce) cache_tree_invalidate_path(active_cache_tree, ce->name); } -static int verify_clean_subdirectory(const char *path, const char *action, +/* + * Check that checking out ce->sha1 in subdir ce->name is not + * going to overwrite any working files. + * + * Currently, git does not checkout subprojects during a superproject + * checkout, so it is not going to overwrite anything. + */ +static int verify_clean_submodule(struct cache_entry *ce, const char *action, + struct unpack_trees_options *o) +{ + return 0; +} + +static int verify_clean_subdirectory(struct cache_entry *ce, const char *action, struct unpack_trees_options *o) { /* - * we are about to extract "path"; we would not want to lose + * we are about to extract "ce->name"; we would not want to lose * anything in the existing directory there. */ int namelen; @@ -437,13 +451,24 @@ static int verify_clean_subdirectory(const char *path, const char *action, struct dir_struct d; char *pathbuf; int cnt = 0; + unsigned char sha1[20]; + + if (S_ISGITLINK(ntohl(ce->ce_mode)) && + resolve_gitlink_ref(ce->name, "HEAD", sha1) == 0) { + /* If we are not going to update the submodule, then + * we don't care. + */ + if (!hashcmp(sha1, ce->sha1)) + return 0; + return verify_clean_submodule(ce, action, o); + } /* * First let's make sure we do not have a local modification * in that directory. */ - namelen = strlen(path); - pos = cache_name_pos(path, namelen); + namelen = strlen(ce->name); + pos = cache_name_pos(ce->name, namelen); if (0 <= pos) return cnt; /* we have it as nondirectory */ pos = -pos - 1; @@ -451,7 +476,7 @@ static int verify_clean_subdirectory(const char *path, const char *action, struct cache_entry *ce = active_cache[i]; int len = ce_namelen(ce); if (len < namelen || - strncmp(path, ce->name, namelen) || + strncmp(ce->name, ce->name, namelen) || ce->name[namelen] != '/') break; /* @@ -469,16 +494,16 @@ static int verify_clean_subdirectory(const char *path, const char *action, * present file that is not ignored. */ pathbuf = xmalloc(namelen + 2); - memcpy(pathbuf, path, namelen); + memcpy(pathbuf, ce->name, namelen); strcpy(pathbuf+namelen, "/"); memset(&d, 0, sizeof(d)); if (o->dir) d.exclude_per_dir = o->dir->exclude_per_dir; - i = read_directory(&d, path, pathbuf, namelen+1, NULL); + i = read_directory(&d, ce->name, pathbuf, namelen+1, NULL); if (i) die("Updating '%s' would lose untracked files in it", - path); + ce->name); free(pathbuf); return cnt; } @@ -487,7 +512,7 @@ static int verify_clean_subdirectory(const char *path, const char *action, * We do not want to remove or overwrite a working tree file that * is not tracked, unless it is ignored. */ -static void verify_absent(const char *path, const char *action, +static void verify_absent(struct cache_entry *ce, const char *action, struct unpack_trees_options *o) { struct stat st; @@ -495,15 +520,15 @@ static void verify_absent(const char *path, const char *action, if (o->index_only || o->reset || !o->update) return; - if (has_symlink_leading_path(path, NULL)) + if (has_symlink_leading_path(ce->name, NULL)) return; - if (!lstat(path, &st)) { + if (!lstat(ce->name, &st)) { int cnt; - if (o->dir && excluded(o->dir, path)) + if (o->dir && excluded(o->dir, ce->name)) /* - * path is explicitly excluded, so it is Ok to + * ce->name is explicitly excluded, so it is Ok to * overwrite it. */ return; @@ -515,7 +540,7 @@ static void verify_absent(const char *path, const char *action, * files that are in "foo/" we would lose * it. */ - cnt = verify_clean_subdirectory(path, action, o); + cnt = verify_clean_subdirectory(ce, action, o); /* * If this removed entries from the index, @@ -543,7 +568,7 @@ static void verify_absent(const char *path, const char *action, * delete this path, which is in a subdirectory that * is being replaced with a blob. */ - cnt = cache_name_pos(path, strlen(path)); + cnt = cache_name_pos(ce->name, strlen(ce->name)); if (0 <= cnt) { struct cache_entry *ce = active_cache[cnt]; if (!ce_stage(ce) && !ce->ce_mode) @@ -551,7 +576,7 @@ static void verify_absent(const char *path, const char *action, } die("Untracked working tree file '%s' " - "would be %s by merge.", path, action); + "would be %s by merge.", ce->name, action); } } @@ -575,7 +600,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old, } } else { - verify_absent(merge->name, "overwritten", o); + verify_absent(merge, "overwritten", o); invalidate_ce_path(merge); } @@ -590,7 +615,7 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old, if (old) verify_uptodate(old, o); else - verify_absent(ce->name, "removed", o); + verify_absent(ce, "removed", o); ce->ce_mode = 0; add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); invalidate_ce_path(ce); @@ -707,18 +732,18 @@ int threeway_merge(struct cache_entry **stages, if (o->aggressive) { int head_deleted = !head && !df_conflict_head; int remote_deleted = !remote && !df_conflict_remote; - const char *path = NULL; + struct cache_entry *ce = NULL; if (index) - path = index->name; + ce = index; else if (head) - path = head->name; + ce = head; else if (remote) - path = remote->name; + ce = remote; else { for (i = 1; i < o->head_idx; i++) { if (stages[i] && stages[i] != o->df_conflict_entry) { - path = stages[i]->name; + ce = stages[i]; break; } } @@ -733,8 +758,8 @@ int threeway_merge(struct cache_entry **stages, (remote_deleted && head && head_match)) { if (index) return deleted_entry(index, index, o); - else if (path && !head_deleted) - verify_absent(path, "removed", o); + else if (ce && !head_deleted) + verify_absent(ce, "removed", o); return 0; } /* |