diff options
72 files changed, 1540 insertions, 769 deletions
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 285781d9db..131bcff9b2 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -1,3 +1,30 @@ +Checklist (and a short version for the impatient): + + - make commits of logical units + - check for unnecessary whitespace with "git diff --check" + before committing + - do not check in commented out code or unneeded files + - provide a meaningful commit message + - the first line of the commit message should be a short + description and should skip the full stop + - if you want your work included in git.git, add a + "Signed-off-by: Your Name <your@email.com>" line to the + commit message (or just use the option "-s" when + committing) to confirm that you agree to the Developer's + Certificate of Origin + - do not PGP sign your patch + - use "git format-patch -M" to create the patch + - do not attach your patch, but read in the mail + body, unless you cannot teach your mailer to + leave the formatting of the patch alone. + - be careful doing cut & paste into your mailer, not to + corrupt whitespaces. + - provide additional information (which is unsuitable for + the commit message) between the "---" and the diffstat + - send the patch to the list _and_ the maintainer + +Long version: + I started reading over the SubmittingPatches document for Linux kernel, primarily because I wanted to have a document similar to it for the core GIT to make sure people understand what they are diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt index 5a13187a87..82cb41d279 100644 --- a/Documentation/git-archimport.txt +++ b/Documentation/git-archimport.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir] - <archive/branch> [ <archive/branch> ] + <archive/branch>[:<git-branch>] ... DESCRIPTION ----------- @@ -39,6 +39,19 @@ directory. To follow the development of a project that uses Arch, rerun `git-archimport` with the same parameters as the initial import to perform incremental imports. +While git-archimport will try to create sensible branch names for the +archives that it imports, it is also possible to specify git branch names +manually. To do so, write a git branch name after each <archive/branch> +parameter, separated by a colon. This way, you can shorten the Arch +branch names and convert Arch jargon to git jargon, for example mapping a +"PROJECT--devo--VERSION" branch to "master". + +Associating multiple Arch branches to one git branch is possible; the +result will make the most sense only if no commits are made to the first +branch, after the second branch is created. Still, this is useful to +convert Arch repositories that had been rotated periodically. + + MERGES ------ Patch merge data from Arch is used to mark merges in git as well. git @@ -73,7 +86,9 @@ OPTIONS Use this for compatibility with old-style branch names used by earlier versions of git-archimport. Old-style branch names were category--branch, whereas new-style branch names are - archive,category--branch--version. + archive,category--branch--version. In both cases, names given + on the command-line will override the automatically-generated + ones. -D <depth>:: Follow merge ancestry and attempt to import trees that have been diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 2187eee416..53a7bb0895 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -8,8 +8,9 @@ git-commit - Record changes to the repository SYNOPSIS -------- [verse] -'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg> | - --amend] [--no-verify] [-e] [--author <author>] +'git-commit' [-a | --interactive] [-s] [-v] + [(-c | -C) <commit> | -F <file> | -m <msg> | --amend] + [--no-verify] [-e] [--author <author>] [--] [[-i | -o ]<file>...] DESCRIPTION @@ -35,6 +36,10 @@ methods: before, and to automatically "rm" files that have been removed from the working tree, and perform the actual commit. +5. by using the --interactive switch with the 'commit' command to decide one + by one which files should be part of the commit, before finalizing the + operation. Currently, this is done by invoking `git-add --interactive`. + The gitlink:git-status[1] command can be used to obtain a summary of what is included by any of the above for the next commit by giving the same set of parameters you would give to diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 6624484fe1..68de5881bd 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -16,6 +16,8 @@ SYNOPSIS 'git-config' [--global] [type] --get-all name [value_regex] 'git-config' [--global] [type] --unset name [value_regex] 'git-config' [--global] [type] --unset-all name [value_regex] +'git-config' [--global] [type] --rename-section old_name new_name +'git-config' [--global] [type] --remove-section name 'git-config' [--global] -l | --list DESCRIPTION @@ -74,6 +76,12 @@ OPTIONS --global:: Use global ~/.gitconfig file rather than the repository .git/config. +--remove-section:: + Remove the given section from the configuration file. + +--rename-section:: + Rename the given section to a new name. + --unset:: Remove the line matching the key from config file. diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index 12a531d1e9..044cee9b42 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -8,7 +8,7 @@ git-diff - Show changes between commits, commit and working tree, etc SYNOPSIS -------- -'git-diff' [ --diff-options ] <commit>{0,2} [--] [<path>...] +'git-diff' [<common diff options>] <commit>{0,2} [--] [<path>...] DESCRIPTION ----------- diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 77a14bb076..eaba6fd4c1 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -62,7 +62,18 @@ OPTIONS Dumps the internal marks table to <file> when complete. Marks are written one per line as `:markid SHA-1`. Frontends can use this file to validate imports after they - have been completed. + have been completed, or to save the marks table across + incremental runs. As <file> is only opened and truncated + at checkpoint (or completion) the same path can also be + safely given to \--import-marks. + +--import-marks=<file>:: + Before processing any input, load the marks specified in + <file>. The input file must exist, must be readable, and + must use the same format as produced by \--export-marks. + Multiple options may be supplied to import more than one + set of marks. If a mark is defined to different values, + the last file wins. --export-pack-edges=<file>:: After creating a packfile, print a line of data to @@ -451,7 +462,7 @@ in octal. Git only supports the following modes: In both formats `<path>` is the complete path of the file to be added (if not already existing) or modified (if already existing). -A `<path>` string must use UNIX-style directory seperators (forward +A `<path>` string must use UNIX-style directory separators (forward slash `/`), may contain any byte other than `LF`, and must not start with double quote (`"`). @@ -461,8 +472,8 @@ quoting should be used, e.g. `"path/with\n and \" in it"`. The value of `<path>` must be in canoncial form. That is it must not: * contain an empty directory component (e.g. `foo//bar` is invalid), -* end with a directory seperator (e.g. `foo/` is invalid), -* start with a directory seperator (e.g. `/foo` is invalid), +* end with a directory separator (e.g. `foo/` is invalid), +* start with a directory separator (e.g. `/foo` is invalid), * contain the special component `.` or `..` (e.g. `foo/./bar` and `foo/../bar` are invalid). diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 59f34b9f0d..84eabebe0b 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -9,8 +9,8 @@ git-format-patch - Prepare patches for e-mail submission SYNOPSIS -------- [verse] -'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] [--thread] - [-s | --signoff] [--diff-options] [--start-number <n>] +'git-format-patch' [<common diff options>] [-n | -k] [-o <dir> | --stdout] + [--attach] [--thread] [-s | --signoff] [--start-number <n>] [--in-reply-to=Message-Id] [--suffix=.<sfx>] [--ignore-if-in-upstream] <since>[..<until>] @@ -46,6 +46,8 @@ reference. OPTIONS ------- +include::diff-options.txt[] + -o|--output-directory <dir>:: Use <dir> to store the resulting files, instead of the current working directory. diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index 10e8c46c4c..3cf55111cc 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -25,61 +25,126 @@ The command allows for creation and fast forwarding of sha1 refs local end receive-pack runs, but to the user who is sitting at the send-pack end, it is updating the remote. Confused?) -Before each ref is updated, if $GIT_DIR/hooks/update file exists -and executable, it is called with three parameters: +There are other real-world examples of using update and +post-update hooks found in the Documentation/howto directory. - $GIT_DIR/hooks/update refname sha1-old sha1-new +git-receive-pack honours the receive.denyNonFastForwards config +option, which tells it if updates to a ref should be denied if they +are not fast-forwards. + +OPTIONS +------- +<directory>:: + The repository to sync into. + +pre-receive Hook +---------------- +Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists +and is executable, it will be invoked once, with three parameters +per ref to be updated: + + $GIT_DIR/hooks/pre-receive (refname sha1-old sha1-new)+ + +The refname parameter is relative to $GIT_DIR; e.g. for the master +head this is "refs/heads/master". The two sha1 arguments after +each refname are the object names for the refname before and after +the update. Refs to be created will have sha1-old equal to 0{40}, +while refs to be deleted will have sha1-new equal to 0{40}, otherwise +sha1-old and sha1-new should be valid objects in the repository. + +This hook is called before any refname is updated and before any +fast-forward checks are performed. + +If the pre-receive hook exits with a non-zero exit status no updates +will be performed, and the update, post-receive and post-update +hooks will not be invoked either. This can be useful to quickly +bail out if the update is not to be supported. -The refname parameter is relative to $GIT_DIR; e.g. for the -master head this is "refs/heads/master". Two sha1 are the -object names for the refname before and after the update. Note -that the hook is called before the refname is updated, so either -sha1-old is 0{40} (meaning there is no such ref yet), or it -should match what is recorded in refname. +update Hook +----------- +Before each ref is updated, if $GIT_DIR/hooks/update file exists +and is executable, it is invoked once per ref, with three parameters: -The hook should exit with non-zero status if it wants to -disallow updating the named ref. Otherwise it should exit with -zero. + $GIT_DIR/hooks/update refname sha1-old sha1-new -Using this hook, it is easy to generate mails on updates to -the local repository. This example script sends a mail with -the commits pushed to the repository: +The refname parameter is relative to $GIT_DIR; e.g. for the master +head this is "refs/heads/master". The two sha1 arguments are +the object names for the refname before and after the update. +Note that the hook is called before the refname is updated, +so either sha1-old is 0{40} (meaning there is no such ref yet), +or it should match what is recorded in refname. + +The hook should exit with non-zero status if it wants to disallow +updating the named ref. Otherwise it should exit with zero. + +Successful execution (a zero exit status) of this hook does not +ensure the ref will actully be updated, it is only a prerequisite. +As such it is not a good idea to send notices (e.g. email) from +this hook. Consider using the post-receive hook instead. + +post-receive Hook +----------------- +After all refs were updated (or attempted to be updated), if any +ref update was successful, and if $GIT_DIR/hooks/post-receive +file exists and is executable, it will be invoke once with three +parameters for each successfully updated ref: + + $GIT_DIR/hooks/post-receive (refname sha1-old sha1-new)+ + +The refname parameter is relative to $GIT_DIR; e.g. for the master +head this is "refs/heads/master". The two sha1 arguments after +each refname are the object names for the refname before and after +the update. Refs that were created will have sha1-old equal to +0{40}, while refs that were deleted will have sha1-new equal to +0{40}, otherwise sha1-old and sha1-new should be valid objects in +the repository. + +Using this hook, it is easy to generate mails describing the updates +to the repository. This example script sends one mail message per +ref listing the commits pushed to the repository: #!/bin/sh # mail out commit update information. - if expr "$2" : '0*$' >/dev/null - then - echo "Created a new ref, with the following commits:" - git-rev-list --pretty "$2" - else - echo "New commits:" - git-rev-list --pretty "$3" "^$2" - fi | - mail -s "Changes to ref $1" commit-list@mydomain + while test $# -gt 0 + do + if expr "$2" : '0*$' >/dev/null + then + echo "Created a new ref, with the following commits:" + git-rev-list --pretty "$2" + else + echo "New commits:" + git-rev-list --pretty "$3" "^$2" + fi | + mail -s "Changes to ref $1" commit-list@mydomain + shift; shift; shift; # discard this ref's args + done exit 0 -Another hook $GIT_DIR/hooks/post-update, if exists and -executable, is called with the list of refs that have been -updated. This can be used to implement repository wide cleanup -task if needed. The exit code from this hook invocation is -ignored; the only thing left for git-receive-pack to do at that -point is to exit itself anyway. This hook can be used, for -example, to run "git-update-server-info" if the repository is -packed and is served via a dumb transport. +The exit code from this hook invocation is ignored, however a +non-zero exit code will generate an error message. - #!/bin/sh - exec git-update-server-info +Note that it is possible for refname to not have sha1-new when this +hook runs. This can easily occur if another user modifies the ref +after it was updated by receive-pack, but before the hook was able +to evaluate it. It is recommended that hooks rely on sha1-new +rather than the current value of refname. -There are other real-world examples of using update and -post-update hooks found in the Documentation/howto directory. +post-update Hook +---------------- +After all other processing, if at least one ref was updated, and +if $GIT_DIR/hooks/post-update file exists and is executable, then +post-update will called with the list of refs that have been updated. +This can be used to implement any repository wide cleanup tasks. -git-receive-pack honours the receive.denyNonFastforwards flag, which -tells it if updates to a ref should be denied if they are not fast-forwards. +The exit code from this hook invocation is ignored; the only thing +left for git-receive-pack to do at that point is to exit itself +anyway. -OPTIONS -------- -<directory>:: - The repository to sync into. +This hook can be used, for example, to run "git-update-server-info" +if the repository is packed and is served via a dumb transport. + + #!/bin/sh + exec git-update-server-info SEE ALSO diff --git a/Documentation/git.txt b/Documentation/git.txt index 0577ad0a8c..e875e8318d 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -241,6 +241,12 @@ Identifier Terminology operate on a <tree> object but automatically dereferences <commit> and <tag> objects that point at a <tree>. +<commit-ish>:: + Indicates a commit or tag object name. A + command that takes a <commit-ish> argument ultimately wants to + operate on a <commit> object but automatically dereferences + <tag> objects that point at a <commit>. + <type>:: Indicates that an object type is required. Currently one of: `blob`, `tree`, `commit`, or `tag`. diff --git a/Documentation/install-webdoc.sh b/Documentation/install-webdoc.sh index b3981936e3..cd3a18eb7f 100755 --- a/Documentation/install-webdoc.sh +++ b/Documentation/install-webdoc.sh @@ -2,7 +2,7 @@ T="$1" -for h in *.html *.txt howto/*.txt howto/*.html RelNotes-*.txt +for h in *.html *.txt howto/*.txt howto/*.html RelNotes-*.txt *.css do if test -f "$T/$h" && diff -u -I'Last updated [0-9][0-9]-[A-Z][a-z][a-z]-' "$T/$h" "$h" diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl index e0bc552a64..05dc7b2c7b 100644 --- a/Documentation/sort_glossary.pl +++ b/Documentation/sort_glossary.pl @@ -48,7 +48,7 @@ This list is sorted alphabetically: '; @keys=sort {uc($a) cmp uc($b)} keys %terms; -$pattern='(\b(?<!link:git-)'.join('\b|\b(?<!link:git-)',reverse @keys).'\b)'; +$pattern='(\b(?<!link:git-)'.join('\b|\b(?<!-)',reverse @keys).'\b)'; foreach $key (@keys) { $terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg; print '[[ref_'.no_spaces($key).']]'.$key."::\n" diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index ffd673ec33..d7b227e647 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -437,11 +437,14 @@ We will sometimes represent git history using diagrams like the one below. Commits are shown as "o", and the links between them with lines drawn with - / and \. Time goes left to right: + +................................................ o--o--o <-- Branch A / o--o--o <-- master \ o--o--o <-- Branch B +................................................ If we need to talk about a particular commit, the character "o" may be replaced with another letter or number. @@ -601,8 +604,8 @@ a new stanza: $ cat .git/config ... [remote "linux-nfs"] - url = git://linux-nfs.org/~bfields/git.git - fetch = +refs/heads/*:refs/remotes/linux-nfs-read/* + url = git://linux-nfs.org/pub/nfs-2.6.git + fetch = +refs/heads/*:refs/remotes/linux-nfs/* ... ------------------------------------------------- @@ -1133,17 +1136,9 @@ modified in two different ways in the remote branch and the local branch--then you are warned; the output may look something like this: ------------------------------------------------- -$ git pull . next -Trying really trivial in-index merge... -fatal: Merge requires file-level merging -Nope. -Merging HEAD with 77976da35a11db4580b80ae27e8d65caf5208086 -Merging: -15e2162 world -77976da goodbye -found 1 common ancestor(s): -d122ed4 initial -Auto-merging file.txt +$ git merge next + 100% (4/4) done +Auto-merged file.txt CONFLICT (content): Merge conflict in file.txt Automatic merge failed; fix conflicts and then commit the result. ------------------------------------------------- @@ -1439,7 +1434,7 @@ modifying the working directory, you can do that with gitlink:git-show[1]: ------------------------------------------------- -$ git show HEAD^ path/to/file +$ git show HEAD^:path/to/file ------------------------------------------------- which will display the given version of the file. @@ -1936,25 +1931,29 @@ $ git commit You have performed no merges into mywork, so it is just a simple linear sequence of patches on top of "origin": - +................................................ o--o--o <-- origin \ o--o--o <-- mywork +................................................ Some more interesting work has been done in the upstream project, and "origin" has advanced: +................................................ o--o--O--o--o--o <-- origin \ a--b--c <-- mywork +................................................ At this point, you could use "pull" to merge your changes back in; the result would create a new merge commit, like this: - +................................................ o--o--O--o--o--o <-- origin \ \ a--b--c--m <-- mywork +................................................ However, if you prefer to keep the history in mywork a simple series of commits without any merges, you may instead choose to use @@ -1971,9 +1970,11 @@ point at the latest version of origin, then apply each of the saved patches to the new mywork. The result will look like: +................................................ o--o--O--o--o--o <-- origin \ a'--b'--c' <-- mywork +................................................ In the process, it may discover conflicts. In that case it will stop and allow you to fix the conflicts; after fixing conflicts, use "git @@ -2081,24 +2082,30 @@ The primary problem with rewriting the history of a branch has to do with merging. Suppose somebody fetches your branch and merges it into their branch, with a result something like this: +................................................ o--o--O--o--o--o <-- origin \ \ t--t--t--m <-- their branch: +................................................ Then suppose you modify the last three commits: +................................................ o--o--o <-- new head of origin / o--o--O--o--o--o <-- old head of origin +................................................ If we examined all this history together in one repository, it will look like: +................................................ o--o--o <-- new head of origin / o--o--O--o--o--o <-- old head of origin \ \ t--t--t--m <-- their branch: +................................................ Git has no way of knowing that the new head is an updated version of the old head; it treats this situation exactly the same as it would if @@ -2159,9 +2166,11 @@ commit. Git calls this process a "fast forward". A fast forward looks something like this: +................................................ o--o--o--o <-- old head of the branch \ o--o--o <-- new head of the branch +................................................ In some cases it is possible that the new head will *not* actually be @@ -2169,11 +2178,11 @@ a descendant of the old head. For example, the developer may have realized she made a serious mistake, and decided to backtrack, resulting in a situation like: +................................................ o--o--o--o--a--b <-- old head of the branch \ o--o--o <-- new head of the branch - - +................................................ In this case, "git fetch" will fail, and print out a warning. @@ -1,6 +1,8 @@ # The default target of this Makefile is... all:: +# Define V=1 to have a more verbose compile. +# # Define NO_OPENSSL environment variable if you do not have OpenSSL. # This also implies MOZILLA_SHA1. # @@ -180,7 +182,7 @@ SCRIPT_SH = \ git-merge-one-file.sh git-parse-remote.sh \ git-pull.sh git-rebase.sh \ git-repack.sh git-request-pull.sh git-reset.sh \ - git-revert.sh git-sh-setup.sh \ + git-sh-setup.sh \ git-tag.sh git-verify-tag.sh \ git-applymbox.sh git-applypatch.sh git-am.sh \ git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ @@ -196,7 +198,7 @@ SCRIPT_PERL = \ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ - git-cherry-pick git-status git-instaweb + git-status git-instaweb # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS = \ @@ -223,7 +225,7 @@ EXTRA_PROGRAMS = BUILT_INS = \ git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \ git-get-tar-commit-id$X git-init$X git-repo-config$X \ - git-fsck-objects$X \ + git-fsck-objects$X git-cherry-pick$X \ $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) # what 'all' will build and 'install' will install, in gitexecdir @@ -315,6 +317,7 @@ BUILTIN_OBJS = \ builtin-rerere.o \ builtin-rev-list.o \ builtin-rev-parse.o \ + builtin-revert.o \ builtin-rm.o \ builtin-runstatus.o \ builtin-shortlog.o \ @@ -603,6 +606,31 @@ ifdef NO_PERL_MAKEMAKER export NO_PERL_MAKEMAKER endif +QUIET_SUBDIR0 = $(MAKE) -C # space to separate -C and subdir +QUIET_SUBDIR1 = + +ifneq ($(findstring $(MAKEFLAGS),w),w) +PRINT_DIR = --no-print-directory +else # "make -w" +NO_SUBDIR = : +endif + +ifneq ($(findstring $(MAKEFLAGS),s),s) +ifndef V + QUIET_CC = @echo ' ' CC $@; + QUIET_AR = @echo ' ' AR $@; + QUIET_LINK = @echo ' ' LINK $@; + QUIET_BUILT_IN = @echo ' ' BUILTIN $@; + QUIET_GEN = @echo ' ' GEN $@; + QUIET_SUBDIR0 = @subdir= + QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ + $(MAKE) $(PRINT_DIR) -C $$subdir + export V + export QUIET_GEN + export QUIET_BUILT_IN +endif +endif + # Shell quote (do not use $(call) to accommodate ancient setups); SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER)) @@ -637,44 +665,43 @@ ifneq (,$X) endif all:: - $(MAKE) -C git-gui all - $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all - $(MAKE) -C templates + $(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all + $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all + $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) strip: $(PROGRAMS) git$X $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS - $(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ + $(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) help.o: common-cmds.h $(BUILT_INS): git$X - rm -f $@ && ln git$X $@ + $(QUIET_BUILT_IN)rm -f $@ && ln git$X $@ common-cmds.h: Documentation/git-*.txt - ./generate-cmdlist.sh > $@+ - mv $@+ $@ + $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh - rm -f $@ $@+ + $(QUIET_GEN)rm -f $@ $@+ && \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ - $@.sh >$@+ - chmod +x $@+ + $@.sh >$@+ && \ + chmod +x $@+ && \ mv $@+ $@ $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak perl/perl.mak: GIT-CFLAGS - $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F) + $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F) $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl - rm -f $@ $@+ + $(QUIET_GEN)rm -f $@ $@+ && \ INSTLIBDIR=`$(MAKE) -C perl -s --no-print-directory instlibdir` && \ sed -e '1{' \ -e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \ @@ -685,20 +712,15 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl -e '}' \ -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ - $@.perl >$@+ - chmod +x $@+ - mv $@+ $@ - -git-cherry-pick: git-revert - cp $< $@+ + $@.perl >$@+ && \ + chmod +x $@+ && \ mv $@+ $@ git-status: git-commit - cp $< $@+ - mv $@+ $@ + $(QUIET_GEN)cp $< $@+ && mv $@+ $@ gitweb/gitweb.cgi: gitweb/gitweb.perl - rm -f $@ $@+ + $(QUIET_GEN)rm -f $@ $@+ && \ sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \ -e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \ -e 's|++GIT_BINDIR++|$(bindir)|g' \ @@ -716,12 +738,12 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl -e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \ -e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \ -e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \ - $< >$@+ - chmod +x $@+ + $< >$@+ && \ + chmod +x $@+ && \ mv $@+ $@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css - rm -f $@ $@+ + $(QUIET_GEN)rm -f $@ $@+ && \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ @@ -729,15 +751,15 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css -e '/@@GITWEB_CGI@@/d' \ -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \ -e '/@@GITWEB_CSS@@/d' \ - $@.sh > $@+ - chmod +x $@+ + $@.sh > $@+ && \ + chmod +x $@+ && \ mv $@+ $@ configure: configure.ac - rm -f $@ $<+ + $(QUIET_GEN)rm -f $@ $<+ && \ sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ - $< > $<+ - autoconf -o $@ $<+ + $< > $<+ && \ + autoconf -o $@ $<+ && \ rm -f $<+ # These can record GIT_VERSION @@ -747,25 +769,25 @@ git$X git.spec \ : GIT-VERSION-FILE %.o: %.c GIT-CFLAGS - $(CC) -o $*.o -c $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< %.o: %.S - $(CC) -o $*.o -c $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< exec_cmd.o: exec_cmd.c GIT-CFLAGS - $(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $< builtin-init-db.o: builtin-init-db.c GIT-CFLAGS - $(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $< http.o: http.c GIT-CFLAGS - $(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $< ifdef NO_EXPAT http-fetch.o: http-fetch.c http.h GIT-CFLAGS - $(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $< + $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $< endif git-%$X: %.o $(GITLIBS) - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) ssh-pull.o: ssh-fetch.c ssh-push.o: ssh-upload.c @@ -779,11 +801,11 @@ git-imap-send$X: imap-send.o $(LIB_FILE) http.o http-fetch.o http-push.o: http.h git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS) - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) git-http-push$X: revision.o http.o http-push.o $(GITLIBS) - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H) @@ -791,7 +813,7 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) - rm -f $@ && $(AR) rcs $@ $(LIB_OBJS) + $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(LIB_OBJS) XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \ xdiff/xmerge.o @@ -799,7 +821,7 @@ $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \ xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h $(XDIFF_LIB): $(XDIFF_OBJS) - rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS) + $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS) perl/Makefile: perl/Git.pm perl/Makefile.PL GIT-CFLAGS diff --git a/builtin-apply.c b/builtin-apply.c index 53935109a3..dfa1716796 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1981,7 +1981,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * } } else if (patch->old_name) { - size = st->st_size; + size = xsize_t(st->st_size); alloc = size + 8192; buf = xmalloc(alloc); if (read_old_data(st, patch->old_name, &buf, &alloc, &size)) diff --git a/builtin-blame.c b/builtin-blame.c index 9f7dd4e19f..b51cdc71fa 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -1244,26 +1244,26 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt) */ struct commit_info { - char *author; - char *author_mail; + const char *author; + const char *author_mail; unsigned long author_time; - char *author_tz; + const char *author_tz; /* filled only when asked for details */ - char *committer; - char *committer_mail; + const char *committer; + const char *committer_mail; unsigned long committer_time; - char *committer_tz; + const char *committer_tz; - char *summary; + const char *summary; }; /* * Parse author/committer line in the commit object buffer */ static void get_ac_line(const char *inbuf, const char *what, - int bufsz, char *person, char **mail, - unsigned long *time, char **tz) + int bufsz, char *person, const char **mail, + unsigned long *time, const char **tz) { int len; char *tmp, *endp; @@ -1280,7 +1280,7 @@ static void get_ac_line(const char *inbuf, const char *what, if (bufsz <= len) { error_out: /* Ugh */ - person = *mail = *tz = "(unknown)"; + *mail = *tz = "(unknown)"; *time = 0; return; } @@ -1963,7 +1963,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con die("Cannot lstat %s", path); read_from = path; } - fin_size = st.st_size; + fin_size = xsize_t(st.st_size); buf = xmalloc(fin_size+1); mode = canon_mode(st.st_mode); switch (st.st_mode & S_IFMT) { diff --git a/builtin-branch.c b/builtin-branch.c index d371849655..06d8a8ce04 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -289,12 +289,13 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev) detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached) { struct ref_item item; - item.name = "(no branch)"; + item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; hashcpy(item.sha1, head_sha1); if (strlen(item.name) > ref_list.maxwidth) ref_list.maxwidth = strlen(item.name); print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1); + free(item.name); } for (i = 0; i < ref_list.index; i++) { diff --git a/builtin-bundle.c b/builtin-bundle.c index d41a413b58..279b8f8e58 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -263,6 +263,11 @@ static void show_object(struct object_array_entry *p) write_or_die(1, "\n", 1); } +static void show_edge(struct commit *commit) +{ + ; /* nothing to do */ +} + static int create_bundle(struct bundle_header *header, const char *path, int argc, const char **argv) { @@ -341,6 +346,7 @@ static int create_bundle(struct bundle_header *header, const char *path, dup2(in, 1); close(in); prepare_revision_walk(&revs); + mark_edges_uninteresting(revs.commits, &revs, show_edge); traverse_commit_list(&revs, show_commit, show_object); close(1); while (waitpid(pid, &status, 0) < 0) diff --git a/builtin-config.c b/builtin-config.c index f1433a4ab6..dfa403b94b 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -2,7 +2,7 @@ #include "cache.h" static const char git_config_set_usage[] = -"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --list"; +"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list"; static char *key; static regex_t *key_regexp; @@ -168,6 +168,19 @@ int cmd_config(int argc, const char **argv, const char *prefix) } return 0; } + else if (!strcmp(argv[1], "--remove-section")) { + int ret; + if (argc != 3) + usage(git_config_set_usage); + ret = git_config_rename_section(argv[2], NULL); + if (ret < 0) + return ret; + if (ret == 0) { + fprintf(stderr, "No such section!\n"); + return 1; + } + return 0; + } else break; argc--; diff --git a/builtin-count-objects.c b/builtin-count-objects.c index f5b22bb80e..6263d8af29 100644 --- a/builtin-count-objects.c +++ b/builtin-count-objects.c @@ -44,7 +44,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose, if (lstat(path, &st) || !S_ISREG(st.st_mode)) bad = 1; else - (*loose_size) += st.st_blocks; + (*loose_size) += xsize_t(st.st_blocks); } if (bad) { if (verbose) { diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index b11ca928d6..2b218425aa 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -301,7 +301,7 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un return ""; } -static char *copy_line(const char *buf) +static const char *copy_line(const char *buf) { const char *eol = strchr(buf, '\n'); char *line; @@ -315,7 +315,7 @@ static char *copy_line(const char *buf) return line; } -static char *copy_name(const char *buf) +static const char *copy_name(const char *buf) { const char *eol = strchr(buf, '\n'); const char *eoname = strstr(buf, " <"); @@ -330,7 +330,7 @@ static char *copy_name(const char *buf) return line; } -static char *copy_email(const char *buf) +static const char *copy_email(const char *buf) { const char *email = strchr(buf, '<'); const char *eoemail = strchr(email, '>'); diff --git a/builtin-fsck.c b/builtin-fsck.c index 4d03378c1b..b8e71b640b 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -648,7 +648,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix) verify_pack(p, 0); for (p = packed_git; p; p = p->next) { - int num = num_packed_objects(p); + uint32_t i, num = num_packed_objects(p); for (i = 0; i < num; i++) { unsigned char sha1[20]; nth_packed_object_sha1(p, i, sha1); diff --git a/builtin-grep.c b/builtin-grep.c index 96b70227cf..694da5ba09 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -122,6 +122,8 @@ static int grep_file(struct grep_opt *opt, const char *filename) struct stat st; int i; char *data; + size_t sz; + if (lstat(filename, &st) < 0) { err_ret: if (errno != ENOENT) @@ -132,11 +134,12 @@ static int grep_file(struct grep_opt *opt, const char *filename) return 0; /* empty file -- no grep hit */ if (!S_ISREG(st.st_mode)) return 0; + sz = xsize_t(st.st_size); i = open(filename, O_RDONLY); if (i < 0) goto err_ret; - data = xmalloc(st.st_size + 1); - if (st.st_size != read_in_full(i, data, st.st_size)) { + data = xmalloc(sz + 1); + if (st.st_size != read_in_full(i, data, sz)) { error("'%s': short read %s", filename, strerror(errno)); close(i); free(data); @@ -145,11 +148,12 @@ static int grep_file(struct grep_opt *opt, const char *filename) close(i); if (opt->relative && opt->prefix_length) filename += opt->prefix_length; - i = grep_buffer(opt, filename, data, st.st_size); + i = grep_buffer(opt, filename, data, sz); free(data); return i; } +#ifdef __unix__ static int exec_grep(int argc, const char **argv) { pid_t pid; @@ -298,6 +302,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) } return hit; } +#endif static int grep_cache(struct grep_opt *opt, const char **paths, int cached) { diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 766a37ebe2..f54e8752fb 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -545,10 +545,10 @@ static int decode_b_segment(char *in, char *ot, char *ep) return 0; } -static void convert_to_utf8(char *line, char *charset) +static void convert_to_utf8(char *line, const char *charset) { - static char latin_one[] = "latin1"; - char *input_charset = *charset ? charset : latin_one; + static const char latin_one[] = "latin1"; + const char *input_charset = *charset ? charset : latin_one; char *out = reencode_string(line, metainfo_charset, input_charset); if (!out) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 8cf24f4079..f8ebad0b2f 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -23,7 +23,7 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\ struct object_entry { unsigned char sha1[20]; unsigned long size; /* uncompressed size */ - unsigned long offset; /* offset into the final pack file; + off_t offset; /* offset into the final pack file; * nonzero if already written. */ unsigned int depth; /* delta depth */ @@ -35,7 +35,7 @@ struct object_entry { #define in_pack_header_size delta_size /* only when reusing pack data */ struct object_entry *delta; /* delta base object */ struct packed_git *in_pack; /* already in pack */ - unsigned int in_pack_offset; + off_t in_pack_offset; struct object_entry *delta_child; /* deltified objects who bases me */ struct object_entry *delta_sibling; /* other deltified objects who * uses the same base as me @@ -68,7 +68,7 @@ static int allow_ofs_delta; static struct object_entry **sorted_by_sha, **sorted_by_type; static struct object_entry *objects; -static int nr_objects, nr_alloc, nr_result; +static uint32_t nr_objects, nr_alloc, nr_result; static const char *base_name; static unsigned char pack_file_sha1[20]; static int progress = 1; @@ -101,7 +101,7 @@ static int object_ix_hashsz; * get the object sha1 from the main index. */ struct revindex_entry { - unsigned int offset; + off_t offset; unsigned int nr; }; struct pack_revindex { @@ -114,10 +114,8 @@ static int pack_revindex_hashsz; /* * stats */ -static int written; -static int written_delta; -static int reused; -static int reused_delta; +static uint32_t written, written_delta; +static uint32_t reused, reused_delta; static int pack_revindex_ix(struct packed_git *p) { @@ -185,7 +183,7 @@ static void prepare_pack_revindex(struct pack_revindex *rix) } static struct revindex_entry * find_packed_object(struct packed_git *p, - unsigned int ofs) + off_t ofs) { int num; int lo, hi; @@ -213,15 +211,14 @@ static struct revindex_entry * find_packed_object(struct packed_git *p, die("internal error: pack revindex corrupt"); } -static unsigned long find_packed_object_size(struct packed_git *p, - unsigned long ofs) +static off_t find_packed_object_size(struct packed_git *p, off_t ofs) { struct revindex_entry *entry = find_packed_object(p, ofs); return entry[1].offset - ofs; } static unsigned char *find_packed_object_name(struct packed_git *p, - unsigned long ofs) + off_t ofs) { struct revindex_entry *entry = find_packed_object(p, ofs); return (unsigned char *)(p->index_base + 256) + 24 * entry->nr + 4; @@ -278,8 +275,8 @@ static int encode_header(enum object_type type, unsigned long size, unsigned cha */ static int check_pack_inflate(struct packed_git *p, struct pack_window **w_curs, - unsigned long offset, - unsigned long len, + off_t offset, + off_t len, unsigned long expect) { z_stream stream; @@ -305,8 +302,8 @@ static int check_pack_inflate(struct packed_git *p, static void copy_pack_data(struct sha1file *f, struct packed_git *p, struct pack_window **w_curs, - unsigned long offset, - unsigned long len) + off_t offset, + off_t len) { unsigned char *in; unsigned int avail; @@ -314,7 +311,7 @@ static void copy_pack_data(struct sha1file *f, while (len) { in = use_pack(p, w_curs, offset, &avail); if (avail > len) - avail = len; + avail = (unsigned int)len; sha1write(f, in, avail); offset += avail; len -= avail; @@ -371,14 +368,15 @@ static int revalidate_loose_object(struct object_entry *entry, return check_loose_inflate(map, mapsize, size); } -static unsigned long write_object(struct sha1file *f, +static off_t write_object(struct sha1file *f, struct object_entry *entry) { unsigned long size; enum object_type type; void *buf; unsigned char header[10]; - unsigned hdrlen, datalen; + unsigned hdrlen; + off_t datalen; enum object_type obj_type; int to_reuse = 0; @@ -441,7 +439,7 @@ static unsigned long write_object(struct sha1file *f, * encoding of the relative offset for the delta * base from this object's position in the pack. */ - unsigned long ofs = entry->offset - entry->delta->offset; + off_t ofs = entry->offset - entry->delta->offset; unsigned pos = sizeof(header) - 1; header[pos] = ofs & 127; while (ofs >>= 7) @@ -462,7 +460,7 @@ static unsigned long write_object(struct sha1file *f, else { struct packed_git *p = entry->in_pack; struct pack_window *w_curs = NULL; - unsigned long offset; + off_t offset; if (entry->delta) { obj_type = (allow_ofs_delta && entry->delta->offset) ? @@ -472,7 +470,7 @@ static unsigned long write_object(struct sha1file *f, hdrlen = encode_header(obj_type, entry->size, header); sha1write(f, header, hdrlen); if (obj_type == OBJ_OFS_DELTA) { - unsigned long ofs = entry->offset - entry->delta->offset; + off_t ofs = entry->offset - entry->delta->offset; unsigned pos = sizeof(header) - 1; header[pos] = ofs & 127; while (ofs >>= 7) @@ -500,9 +498,9 @@ static unsigned long write_object(struct sha1file *f, return hdrlen + datalen; } -static unsigned long write_one(struct sha1file *f, +static off_t write_one(struct sha1file *f, struct object_entry *e, - unsigned long offset) + off_t offset) { if (e->offset || e->preferred_base) /* offset starts from header size and cannot be zero @@ -518,9 +516,9 @@ static unsigned long write_one(struct sha1file *f, static void write_pack_file(void) { - int i; + uint32_t i; struct sha1file *f; - unsigned long offset; + off_t offset; struct pack_header hdr; unsigned last_percent = 999; int do_progress = progress; @@ -533,7 +531,7 @@ static void write_pack_file(void) f = sha1create("%s-%s.%s", base_name, sha1_to_hex(object_list_sha1), "pack"); if (do_progress) - fprintf(stderr, "Writing %d objects.\n", nr_result); + fprintf(stderr, "Writing %u objects.\n", nr_result); hdr.hdr_signature = htonl(PACK_SIGNATURE); hdr.hdr_version = htonl(PACK_VERSION); @@ -558,13 +556,13 @@ static void write_pack_file(void) fputc('\n', stderr); done: if (written != nr_result) - die("wrote %d objects while expecting %d", written, nr_result); + die("wrote %u objects while expecting %u", written, nr_result); sha1close(f, pack_file_sha1, 1); } static void write_index_file(void) { - int i; + uint32_t i; struct sha1file *f = sha1create("%s-%s.%s", base_name, sha1_to_hex(object_list_sha1), "idx"); struct object_entry **list = sorted_by_sha; @@ -633,7 +631,7 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1) static void rehash_objects(void) { - int i; + uint32_t i; struct object_entry *oe; object_ix_hashsz = nr_objects * 3; @@ -670,16 +668,16 @@ static unsigned name_hash(const char *name) static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclude) { - unsigned int idx = nr_objects; + uint32_t idx = nr_objects; struct object_entry *entry; struct packed_git *p; - unsigned int found_offset = 0; + off_t found_offset = 0; struct packed_git *found_pack = NULL; int ix, status = 0; if (!exclude) { for (p = packed_git; p; p = p->next) { - unsigned long offset = find_pack_entry_one(sha1, p); + off_t offset = find_pack_entry_one(sha1, p); if (offset) { if (incremental) return 0; @@ -696,9 +694,8 @@ static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclud goto already_added; if (idx >= nr_alloc) { - unsigned int needed = (idx + 1024) * 3 / 2; - objects = xrealloc(objects, needed * sizeof(*entry)); - nr_alloc = needed; + nr_alloc = (idx + 1024) * 3 / 2; + objects = xrealloc(objects, nr_alloc * sizeof(*entry)); } entry = objects + idx; nr_objects = idx + 1; @@ -718,7 +715,7 @@ static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclud already_added: if (progress_update) { - fprintf(stderr, "Counting objects...%d\r", nr_objects); + fprintf(stderr, "Counting objects...%u\r", nr_objects); progress_update = 0; } if (exclude) @@ -981,17 +978,17 @@ static void check_object(struct object_entry *entry) if (entry->in_pack && !entry->preferred_base) { struct packed_git *p = entry->in_pack; struct pack_window *w_curs = NULL; - unsigned long left = p->pack_size - entry->in_pack_offset; unsigned long size, used; + unsigned int avail; unsigned char *buf; struct object_entry *base_entry = NULL; - buf = use_pack(p, &w_curs, entry->in_pack_offset, NULL); + buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail); /* We want in_pack_type even if we do not reuse delta. * There is no point not reusing non-delta representations. */ - used = unpack_object_header_gently(buf, left, + used = unpack_object_header_gently(buf, avail, &entry->in_pack_type, &size); /* Check if it is delta, and the base is also an object @@ -1000,7 +997,7 @@ static void check_object(struct object_entry *entry) */ if (!no_reuse_delta) { unsigned char c, *base_name; - unsigned long ofs; + off_t ofs; unsigned long used_0; /* there is at least 20 bytes left in the pack */ switch (entry->in_pack_type) { @@ -1081,7 +1078,7 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) static void get_object_details(void) { - int i; + uint32_t i; struct object_entry *entry; prepare_pack_ix(); @@ -1120,7 +1117,7 @@ static int sort_comparator(const void *_a, const void *_b) static struct object_entry **create_sorted_list(entry_sort_t sort) { struct object_entry **list = xmalloc(nr_objects * sizeof(struct object_entry *)); - int i; + uint32_t i; for (i = 0; i < nr_objects; i++) list[i] = objects + i; @@ -1137,7 +1134,7 @@ static int sha1_sort(const struct object_entry *a, const struct object_entry *b) static struct object_entry **create_final_object_list(void) { struct object_entry **list; - int i, j; + uint32_t i, j; for (i = nr_result = 0; i < nr_objects; i++) if (!objects[i].preferred_base) @@ -1279,20 +1276,20 @@ static void progress_interval(int signum) static void find_deltas(struct object_entry **list, int window, int depth) { - int i, idx; + uint32_t i = nr_objects, idx = 0, processed = 0; unsigned int array_size = window * sizeof(struct unpacked); - struct unpacked *array = xmalloc(array_size); - unsigned processed = 0; + struct unpacked *array; unsigned last_percent = 999; + if (!nr_objects) + return; + array = xmalloc(array_size); memset(array, 0, array_size); - i = nr_objects; - idx = 0; if (progress) - fprintf(stderr, "Deltifying %d objects.\n", nr_result); + fprintf(stderr, "Deltifying %u objects.\n", nr_result); - while (--i >= 0) { - struct object_entry *entry = list[i]; + do { + struct object_entry *entry = list[--i]; struct unpacked *n = array + idx; int j; @@ -1325,7 +1322,7 @@ static void find_deltas(struct object_entry **list, int window, int depth) j = window; while (--j > 0) { - unsigned int other_idx = idx + j; + uint32_t other_idx = idx + j; struct unpacked *m; if (other_idx >= window) other_idx -= window; @@ -1345,7 +1342,7 @@ static void find_deltas(struct object_entry **list, int window, int depth) idx++; if (idx >= window) idx = 0; - } + } while (i > 0); if (progress) fputc('\n', stderr); @@ -1386,7 +1383,7 @@ static int reuse_cached_pack(unsigned char *sha1) } if (progress) - fprintf(stderr, "Reusing %d objects pack %s\n", nr_objects, + fprintf(stderr, "Reusing %u objects pack %s\n", nr_objects, sha1_to_hex(sha1)); if (pack_to_stdout) { @@ -1537,7 +1534,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) struct object_entry **list; int use_internal_rev_list = 0; int thin = 0; - int i; + uint32_t i; const char **rp_av; int rp_ac_alloc = 64; int rp_ac; @@ -1670,7 +1667,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) } if (progress) - fprintf(stderr, "Done counting %d objects.\n", nr_objects); + fprintf(stderr, "Done counting %u objects.\n", nr_objects); sorted_by_sha = create_final_object_list(); if (non_empty && !nr_result) return 0; @@ -1683,7 +1680,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) } SHA1_Final(object_list_sha1, &ctx); if (progress && (nr_objects != nr_result)) - fprintf(stderr, "Result has %d objects.\n", nr_result); + fprintf(stderr, "Result has %u objects.\n", nr_result); if (reuse_cached_pack(object_list_sha1)) ; @@ -1704,7 +1701,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) } } if (progress) - fprintf(stderr, "Total %d (delta %d), reused %d (delta %d)\n", + fprintf(stderr, "Total %u (delta %u), reused %u (delta %u)\n", written, written_delta, reused, reused_delta); return 0; } diff --git a/builtin-revert.c b/builtin-revert.c new file mode 100644 index 0000000000..2f2dc1bbaa --- /dev/null +++ b/builtin-revert.c @@ -0,0 +1,399 @@ +#include "cache.h" +#include "builtin.h" +#include "object.h" +#include "commit.h" +#include "tag.h" +#include "wt-status.h" +#include "run-command.h" +#include "exec_cmd.h" +#include "utf8.h" + +/* + * This implements the builtins revert and cherry-pick. + * + * Copyright (c) 2007 Johannes E. Schindelin + * + * Based on git-revert.sh, which is + * + * Copyright (c) 2005 Linus Torvalds + * Copyright (c) 2005 Junio C Hamano + */ + +static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>"; + +static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>"; + +static int edit; +static int replay; +enum { REVERT, CHERRY_PICK } action; +static int no_commit; +static struct commit *commit; +static int needed_deref; + +static const char *me; + +#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" + +static void parse_options(int argc, const char **argv) +{ + const char *usage_str = action == REVERT ? + revert_usage : cherry_pick_usage; + unsigned char sha1[20]; + const char *arg; + int i; + + if (argc < 2) + usage(usage_str); + + for (i = 1; i < argc - 1; i++) { + arg = argv[i]; + if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit")) + no_commit = 1; + else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit")) + edit = 1; + else if (!strcmp(arg, "--no-edit")) + edit = 0; + else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-" + "to-expose-my-private-commit-object-name")) + replay = 0; + else if (strcmp(arg, "-r")) + usage(usage_str); + } + + arg = argv[argc - 1]; + if (get_sha1(arg, sha1)) + die ("Cannot find '%s'", arg); + commit = (struct commit *)parse_object(sha1); + if (!commit) + die ("Could not find %s", sha1_to_hex(sha1)); + if (commit->object.type == OBJ_TAG) { + commit = (struct commit *) + deref_tag((struct object *)commit, arg, strlen(arg)); + needed_deref = 1; + } + if (commit->object.type != OBJ_COMMIT) + die ("'%s' does not point to a commit", arg); +} + +static char *get_oneline(const char *message) +{ + char *result; + const char *p = message, *abbrev, *eol; + int abbrev_len, oneline_len; + + if (!p) + die ("Could not read commit message of %s", + sha1_to_hex(commit->object.sha1)); + while (*p && (*p != '\n' || p[1] != '\n')) + p++; + + if (*p) { + p += 2; + for (eol = p + 1; *eol && *eol != '\n'; eol++) + ; /* do nothing */ + } else + eol = p; + abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV); + abbrev_len = strlen(abbrev); + oneline_len = eol - p; + result = xmalloc(abbrev_len + 5 + oneline_len); + memcpy(result, abbrev, abbrev_len); + memcpy(result + abbrev_len, "... ", 4); + memcpy(result + abbrev_len + 4, p, oneline_len); + result[abbrev_len + 4 + oneline_len] = '\0'; + return result; +} + +char *get_encoding(const char *message) +{ + const char *p = message, *eol; + + if (!p) + die ("Could not read commit message of %s", + sha1_to_hex(commit->object.sha1)); + while (*p && *p != '\n') { + for (eol = p + 1; *eol && *eol != '\n'; eol++) + ; /* do nothing */ + if (!prefixcmp(p, "encoding ")) { + char *result = xmalloc(eol - 8 - p); + strlcpy(result, p + 9, eol - 8 - p); + return result; + } + p = eol; + if (*p == '\n') + p++; + } + return NULL; +} + +struct lock_file msg_file; +static int msg_fd; + +static void add_to_msg(const char *string) +{ + int len = strlen(string); + if (write_in_full(msg_fd, string, len) < 0) + die ("Could not write to .msg"); +} + +static void add_message_to_msg(const char *message) +{ + const char *p = message; + while (*p && (*p != '\n' || p[1] != '\n')) + p++; + + if (!*p) + add_to_msg(sha1_to_hex(commit->object.sha1)); + + p += 2; + add_to_msg(p); + return; +} + +static void set_author_ident_env(const char *message) +{ + const char *p = message; + if (!p) + die ("Could not read commit message of %s", + sha1_to_hex(commit->object.sha1)); + while (*p && *p != '\n') { + const char *eol; + + for (eol = p; *eol && *eol != '\n'; eol++) + ; /* do nothing */ + if (!prefixcmp(p, "author ")) { + char *line, *pend, *email, *timestamp; + + p += 7; + line = xmalloc(eol + 1 - p); + memcpy(line, p, eol - p); + line[eol - p] = '\0'; + email = strchr(line, '<'); + if (!email) + die ("Could not extract author email from %s", + sha1_to_hex(commit->object.sha1)); + if (email == line) + pend = line; + else + for (pend = email; pend != line + 1 && + isspace(pend[-1]); pend--); + ; /* do nothing */ + *pend = '\0'; + email++; + timestamp = strchr(email, '>'); + if (!timestamp) + die ("Could not extract author email from %s", + sha1_to_hex(commit->object.sha1)); + *timestamp = '\0'; + for (timestamp++; *timestamp && isspace(*timestamp); + timestamp++) + ; /* do nothing */ + setenv("GIT_AUTHOR_NAME", line, 1); + setenv("GIT_AUTHOR_EMAIL", email, 1); + setenv("GIT_AUTHOR_DATE", timestamp, 1); + free(line); + return; + } + p = eol; + if (*p == '\n') + p++; + } + die ("No author information found in %s", + sha1_to_hex(commit->object.sha1)); +} + +static int merge_recursive(const char *base_sha1, + const char *head_sha1, const char *head_name, + const char *next_sha1, const char *next_name) +{ + char buffer[256]; + + sprintf(buffer, "GITHEAD_%s", head_sha1); + setenv(buffer, head_name, 1); + sprintf(buffer, "GITHEAD_%s", next_sha1); + setenv(buffer, next_name, 1); + + /* + * This three way merge is an interesting one. We are at + * $head, and would want to apply the change between $commit + * and $prev on top of us (when reverting), or the change between + * $prev and $commit on top of us (when cherry-picking or replaying). + */ + + return run_command_opt(RUN_COMMAND_NO_STDIN | RUN_GIT_CMD, + "merge-recursive", base_sha1, "--", + head_sha1, next_sha1, NULL); +} + +static int revert_or_cherry_pick(int argc, const char **argv) +{ + unsigned char head[20]; + struct commit *base, *next; + int i; + char *oneline, *encoding, *reencoded_message = NULL; + const char *message; + + git_config(git_default_config); + me = action == REVERT ? "revert" : "cherry-pick"; + setenv(GIT_REFLOG_ACTION, me, 0); + parse_options(argc, argv); + + /* this is copied from the shell script, but it's never triggered... */ + if (action == REVERT && replay) + die("revert is incompatible with replay"); + + if (no_commit) { + /* + * We do not intend to commit immediately. We just want to + * merge the differences in. + */ + if (write_tree(head, 0, NULL)) + die ("Your index file is unmerged."); + } else { + struct wt_status s; + + if (get_sha1("HEAD", head)) + die ("You do not have a valid HEAD"); + wt_status_prepare(&s); + if (s.commitable || s.workdir_dirty) + die ("Dirty index: cannot %s", me); + discard_cache(); + } + + if (!commit->parents) + die ("Cannot %s a root commit", me); + if (commit->parents->next) + die ("Cannot %s a multi-parent commit.", me); + if (!(message = commit->buffer)) + die ("Cannot get commit message for %s", + sha1_to_hex(commit->object.sha1)); + + /* + * "commit" is an existing commit. We would want to apply + * the difference it introduces since its first parent "prev" + * on top of the current HEAD if we are cherry-pick. Or the + * reverse of it if we are revert. + */ + + msg_fd = hold_lock_file_for_update(&msg_file, ".msg", 1); + + encoding = get_encoding(message); + if (!encoding) + encoding = "utf-8"; + if (!git_commit_encoding) + git_commit_encoding = "utf-8"; + if ((reencoded_message = reencode_string(message, + git_commit_encoding, encoding))) + message = reencoded_message; + + oneline = get_oneline(message); + + if (action == REVERT) { + base = commit; + next = commit->parents->item; + add_to_msg("Revert "); + add_to_msg(find_unique_abbrev(commit->object.sha1, + DEFAULT_ABBREV)); + add_to_msg(oneline); + add_to_msg("\nThis reverts commit "); + add_to_msg(sha1_to_hex(commit->object.sha1)); + add_to_msg(".\n"); + } else { + base = commit->parents->item; + next = commit; + set_author_ident_env(message); + add_message_to_msg(message); + if (!replay) { + add_to_msg("(cherry picked from commit "); + add_to_msg(sha1_to_hex(commit->object.sha1)); + add_to_msg(")\n"); + } + } + if (needed_deref) { + add_to_msg("(original 'git "); + add_to_msg(me); + add_to_msg("' arguments: "); + for (i = 0; i < argc; i++) { + if (i) + add_to_msg(" "); + add_to_msg(argv[i]); + } + add_to_msg(")\n"); + } + + if (merge_recursive(sha1_to_hex(base->object.sha1), + sha1_to_hex(head), "HEAD", + sha1_to_hex(next->object.sha1), oneline) || + write_tree(head, 0, NULL)) { + const char *target = git_path("MERGE_MSG"); + add_to_msg("\nConflicts:\n\n"); + read_cache(); + for (i = 0; i < active_nr;) { + struct cache_entry *ce = active_cache[i++]; + if (ce_stage(ce)) { + add_to_msg("\t"); + add_to_msg(ce->name); + add_to_msg("\n"); + while (i < active_nr && !strcmp(ce->name, + active_cache[i]->name)) + i++; + } + } + if (close(msg_fd) || commit_lock_file(&msg_file) < 0) + die ("Error wrapping up .msg"); + unlink(target); + if (rename(".msg", target)) + die ("Could not move .msg to %s", target); + fprintf(stderr, "Automatic %s failed. " + "After resolving the conflicts,\n" + "mark the corrected paths with 'git-add <paths>'\n" + "and commit the result.\n", me); + if (action == CHERRY_PICK) { + fprintf(stderr, "When commiting, use the option " + "'-c %s' to retain authorship and message.\n", + find_unique_abbrev(commit->object.sha1, + DEFAULT_ABBREV)); + } + exit(1); + } + if (close(msg_fd) || commit_lock_file(&msg_file) < 0) + die ("Error wrapping up .msg"); + fprintf(stderr, "Finished one %s.\n", me); + + /* + * + * If we are cherry-pick, and if the merge did not result in + * hand-editing, we will hit this commit and inherit the original + * author date and name. + * If we are revert, or if our cherry-pick results in a hand merge, + * we had better say that the current user is responsible for that. + */ + + if (!no_commit) { + if (edit) + return execl_git_cmd("commit", "-n", "-F", ".msg", + "-e", NULL); + else + return execl_git_cmd("commit", "-n", "-F", ".msg", + NULL); + } + if (reencoded_message) + free(reencoded_message); + + return 0; +} + +int cmd_revert(int argc, const char **argv, const char *prefix) +{ + if (isatty(0)) + edit = 1; + action = REVERT; + return revert_or_cherry_pick(argc, argv); +} + +int cmd_cherry_pick(int argc, const char **argv, const char *prefix) +{ + replay = 1; + action = CHERRY_PICK; + return revert_or_cherry_pick(argc, argv); +} diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 2f71a2a6e2..2d7726e8b9 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -217,13 +217,13 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list) prepare_revision_walk(rev); while ((commit = get_revision(rev)) != NULL) { - char *author = NULL, *oneline, *buffer; + const char *author = NULL, *oneline, *buffer; int authorlen = authorlen, onelinelen; /* get author and oneline */ for (buffer = commit->buffer; buffer && *buffer != '\0' && *buffer != '\n'; ) { - char *eol = strchr(buffer, '\n'); + const char *eol = strchr(buffer, '\n'); if (eol == NULL) eol = buffer + strlen(buffer); diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 67ae6bacda..c892f1f7a6 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -721,7 +721,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) } for (i = 0; i < reflog; i++) { - char *logmsg, *msg, *m; + char *logmsg, *m; + const char *msg; unsigned long timestamp; int tz; @@ -24,6 +24,7 @@ extern int cmd_cat_file(int argc, const char **argv, const char *prefix); extern int cmd_checkout_index(int argc, const char **argv, const char *prefix); extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix); extern int cmd_cherry(int argc, const char **argv, const char *prefix); +extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix); extern int cmd_commit_tree(int argc, const char **argv, const char *prefix); extern int cmd_count_objects(int argc, const char **argv, const char *prefix); extern int cmd_describe(int argc, const char **argv, const char *prefix); @@ -60,6 +61,7 @@ extern int cmd_config(int argc, const char **argv, const char *prefix); extern int cmd_rerere(int argc, const char **argv, const char *prefix); extern int cmd_rev_list(int argc, const char **argv, const char *prefix); extern int cmd_rev_parse(int argc, const char **argv, const char *prefix); +extern int cmd_revert(int argc, const char **argv, const char *prefix); extern int cmd_rm(int argc, const char **argv, const char *prefix); extern int cmd_runstatus(int argc, const char **argv, const char *prefix); extern int cmd_shortlog(int argc, const char **argv, const char *prefix); @@ -382,7 +382,7 @@ extern struct packed_git { } *packed_git; struct pack_entry { - unsigned int offset; + off_t offset; unsigned char sha1[20]; struct packed_git *p; }; @@ -421,15 +421,15 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); extern void pack_report(void); -extern unsigned char* use_pack(struct packed_git *, struct pack_window **, unsigned long, unsigned int *); +extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *); extern void unuse_pack(struct pack_window **); extern struct packed_git *add_packed_git(char *, int, int); -extern int num_packed_objects(const struct packed_git *p); -extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); -extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *); -extern void *unpack_entry(struct packed_git *, unsigned long, enum object_type *, unsigned long *); +extern uint32_t num_packed_objects(const struct packed_git *p); +extern int nth_packed_object_sha1(const struct packed_git *, uint32_t, unsigned char*); +extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *); +extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *); extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); -extern const char *packed_object_info_detail(struct packed_git *, unsigned long, unsigned long *, unsigned long *, unsigned int *, unsigned char *); +extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *); /* Dumb servers support */ extern int update_server_info(int); @@ -450,7 +450,7 @@ extern char git_default_email[MAX_GITNAME]; extern char git_default_name[MAX_GITNAME]; extern char *git_commit_encoding; -extern char *git_log_output_encoding; +extern const char *git_log_output_encoding; extern int copy_fd(int ifd, int ofd); extern int read_in_full(int fd, void *buf, size_t count); diff --git a/combine-diff.c b/combine-diff.c index 6d928f282a..3a9b32f6b8 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -684,7 +684,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, goto deleted_file; if (S_ISLNK(st.st_mode)) { - size_t len = st.st_size; + size_t len = xsize_t(st.st_size); result_size = len; result = xmalloc(len + 1); if (result_size != readlink(elem->path, result, len)) { @@ -697,7 +697,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } else if (0 <= (fd = open(elem->path, O_RDONLY)) && !fstat(fd, &st)) { - size_t len = st.st_size; + size_t len = xsize_t(st.st_size); size_t sz = 0; int is_file, i; @@ -651,7 +651,7 @@ static char *get_header(const struct commit *commit, const char *key) } } -static char *replace_encoding_header(char *buf, char *encoding) +static char *replace_encoding_header(char *buf, const char *encoding) { char *encoding_header = strstr(buf, "\nencoding "); char *end_of_encoding_header; @@ -694,29 +694,26 @@ static char *replace_encoding_header(char *buf, char *encoding) } static char *logmsg_reencode(const struct commit *commit, - char *output_encoding) + const char *output_encoding) { + static const char *utf8 = "utf-8"; + const char *use_encoding; char *encoding; char *out; - char *utf8 = "utf-8"; if (!*output_encoding) return NULL; encoding = get_header(commit, "encoding"); - if (!encoding) - encoding = utf8; - if (!strcmp(encoding, output_encoding)) + use_encoding = encoding ? encoding : utf8; + if (!strcmp(use_encoding, output_encoding)) out = strdup(commit->buffer); else out = reencode_string(commit->buffer, - output_encoding, encoding); + output_encoding, use_encoding); if (out) out = replace_encoding_header(out, output_encoding); - if (encoding != utf8) - free(encoding); - if (!out) - return NULL; + free(encoding); return out; } @@ -917,7 +914,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg = commit->buffer; int plain_non_ascii = 0; char *reencoded; - char *encoding; + const char *encoding; if (fmt == CMIT_FMT_USERFORMAT) return format_commit_message(commit, msg, buf, space); @@ -431,7 +431,7 @@ static struct { int do_not_match; regex_t* value_regex; int multi_replace; - off_t offset[MAX_MATCHES]; + size_t offset[MAX_MATCHES]; enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state; int seen; } store; @@ -579,11 +579,11 @@ static int store_write_pair(int fd, const char* key, const char* value) return 1; } -static int find_beginning_of_line(const char* contents, int size, - int offset_, int* found_bracket) +static ssize_t find_beginning_of_line(const char* contents, size_t size, + size_t offset_, int* found_bracket) { - int equal_offset = size, bracket_offset = size; - int offset; + size_t equal_offset = size, bracket_offset = size; + ssize_t offset; for (offset = offset_-2; offset > 0 && contents[offset] != '\n'; offset--) @@ -727,7 +727,8 @@ int git_config_set_multivar(const char* key, const char* value, } else { struct stat st; char* contents; - int i, copy_begin, copy_end, new_line = 0; + size_t contents_sz, copy_begin, copy_end; + int i, new_line = 0; if (value_regex == NULL) store.value_regex = NULL; @@ -784,7 +785,8 @@ int git_config_set_multivar(const char* key, const char* value, } fstat(in_fd, &st); - contents = xmmap(NULL, st.st_size, PROT_READ, + contents_sz = xsize_t(st.st_size); + contents = xmmap(NULL, contents_sz, PROT_READ, MAP_PRIVATE, in_fd, 0); close(in_fd); @@ -793,12 +795,12 @@ int git_config_set_multivar(const char* key, const char* value, for (i = 0, copy_begin = 0; i < store.seen; i++) { if (store.offset[i] == 0) { - store.offset[i] = copy_end = st.st_size; + store.offset[i] = copy_end = contents_sz; } else if (store.state != KEY_SEEN) { copy_end = store.offset[i]; } else copy_end = find_beginning_of_line( - contents, st.st_size, + contents, contents_sz, store.offset[i]-2, &new_line); /* write the first part of the config */ @@ -825,13 +827,13 @@ int git_config_set_multivar(const char* key, const char* value, } /* write the rest of the config */ - if (copy_begin < st.st_size) + if (copy_begin < contents_sz) if (write_in_full(fd, contents + copy_begin, - st.st_size - copy_begin) < - st.st_size - copy_begin) + contents_sz - copy_begin) < + contents_sz - copy_begin) goto write_err_out; - munmap(contents, st.st_size); + munmap(contents, contents_sz); unlink(config_filename); } @@ -859,9 +861,37 @@ write_err_out: } +static int section_name_match (const char *buf, const char *name) +{ + int i = 0, j = 0, dot = 0; + for (; buf[i] && buf[i] != ']'; i++) { + if (!dot && isspace(buf[i])) { + dot = 1; + if (name[j++] != '.') + break; + for (i++; isspace(buf[i]); i++) + ; /* do nothing */ + if (buf[i] != '"') + break; + continue; + } + if (buf[i] == '\\' && dot) + i++; + else if (buf[i] == '"' && dot) { + for (i++; isspace(buf[i]); i++) + ; /* do_nothing */ + break; + } + if (buf[i] != name[j++]) + break; + } + return (buf[i] == ']' && name[j] == 0); +} + +/* if new_name == NULL, the section is removed instead */ int git_config_rename_section(const char *old_name, const char *new_name) { - int ret = 0; + int ret = 0, remove = 0; char *config_filename; struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1); int out_fd; @@ -892,31 +922,12 @@ int git_config_rename_section(const char *old_name, const char *new_name) ; /* do nothing */ if (buf[i] == '[') { /* it's a section */ - int j = 0, dot = 0; - for (i++; buf[i] && buf[i] != ']'; i++) { - if (!dot && isspace(buf[i])) { - dot = 1; - if (old_name[j++] != '.') - break; - for (i++; isspace(buf[i]); i++) - ; /* do nothing */ - if (buf[i] != '"') - break; + if (section_name_match (&buf[i+1], old_name)) { + ret++; + if (new_name == NULL) { + remove = 1; continue; } - if (buf[i] == '\\' && dot) - i++; - else if (buf[i] == '"' && dot) { - for (i++; isspace(buf[i]); i++) - ; /* do_nothing */ - break; - } - if (buf[i] != old_name[j++]) - break; - } - if (buf[i] == ']' && old_name[j] == 0) { - /* old_name matches */ - ret++; store.baselen = strlen(new_name); if (!store_write_section(out_fd, new_name)) { ret = write_error(); @@ -924,7 +935,10 @@ int git_config_rename_section(const char *old_name, const char *new_name) } continue; } + remove = 0; } + if (remove) + continue; length = strlen(buf); if (write_in_full(out_fd, buf, length) != length) { ret = write_error(); diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 13d198229b..db87a37895 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -891,36 +891,77 @@ and returns the process output as a string." (with-current-buffer log-edit-parent-buffer (git-get-filenames (git-marked-files-state 'added 'deleted 'modified)))) +(defun git-append-sign-off (name email) + "Append a Signed-off-by entry to the current buffer, avoiding duplicates." + (let ((sign-off (format "Signed-off-by: %s <%s>" name email)) + (case-fold-search t)) + (goto-char (point-min)) + (unless (re-search-forward (concat "^" (regexp-quote sign-off)) nil t) + (goto-char (point-min)) + (unless (re-search-forward "^Signed-off-by: " nil t) + (setq sign-off (concat "\n" sign-off))) + (goto-char (point-max)) + (insert sign-off "\n")))) + +(defun git-setup-log-buffer (buffer &optional author-name author-email subject date msg) + "Setup the log buffer for a commit." + (unless git-status (error "Not in git-status buffer.")) + (let ((merge-heads (git-get-merge-heads)) + (dir default-directory) + (committer-name (git-get-committer-name)) + (committer-email (git-get-committer-email)) + (sign-off git-append-signed-off-by)) + (with-current-buffer buffer + (cd dir) + (erase-buffer) + (insert + (propertize + (format "Author: %s <%s>\n%s%s" + (or author-name committer-name) + (or author-email committer-email) + (if date (format "Date: %s\n" date) "") + (if merge-heads + (format "Parent: %s\n%s\n" + (git-rev-parse "HEAD") + (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n")) + "")) + 'face 'git-header-face) + (propertize git-log-msg-separator 'face 'git-separator-face) + "\n") + (when subject (insert subject "\n\n")) + (cond (msg (insert msg "\n")) + ((file-readable-p ".dotest/msg") + (insert-file-contents ".dotest/msg")) + ((file-readable-p ".git/MERGE_MSG") + (insert-file-contents ".git/MERGE_MSG"))) + ; delete empty lines at end + (goto-char (point-min)) + (when (re-search-forward "\n+\\'" nil t) + (replace-match "\n" t t)) + (when sign-off (git-append-sign-off committer-name committer-email))))) + (defun git-commit-file () "Commit the marked file(s), asking for a commit message." (interactive) (unless git-status (error "Not in git-status buffer.")) (let ((buffer (get-buffer-create "*git-commit*")) - (merge-heads (git-get-merge-heads)) - (dir default-directory) (coding-system (git-get-commits-coding-system)) - (sign-off git-append-signed-off-by)) - (with-current-buffer buffer - (when (eq 0 (buffer-size)) - (cd dir) - (erase-buffer) - (insert - (propertize - (format "Author: %s <%s>\n%s" - (git-get-committer-name) (git-get-committer-email) - (if merge-heads - (format "Parent: %s\n%s\n" - (git-rev-parse "HEAD") - (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n")) - "")) - 'face 'git-header-face) - (propertize git-log-msg-separator 'face 'git-separator-face) - "\n") - (cond ((file-readable-p ".git/MERGE_MSG") - (insert-file-contents ".git/MERGE_MSG")) - (sign-off - (insert (format "\n\nSigned-off-by: %s <%s>\n" - (git-get-committer-name) (git-get-committer-email))))))) + author-name author-email subject date) + (when (eq 0 (buffer-size buffer)) + (when (file-readable-p ".dotest/info") + (with-temp-buffer + (insert-file-contents ".dotest/info") + (goto-char (point-min)) + (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t) + (setq author-name (match-string 1)) + (setq author-email (match-string 2))) + (goto-char (point-min)) + (when (re-search-forward "^Subject: \\(.*\\)$" nil t) + (setq subject (match-string 1))) + (goto-char (point-min)) + (when (re-search-forward "^Date: \\(.*\\)$" nil t) + (setq date (match-string 1))))) + (git-setup-log-buffer buffer author-name author-email subject date)) (log-edit #'git-do-commit nil #'git-log-edit-files buffer) (setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords)) (setq buffer-file-coding-system coding-system) diff --git a/convert-objects.c b/convert-objects.c index b5f41ae2e3..4809f9199f 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -132,7 +132,7 @@ static void convert_tree(void *buffer, unsigned long size, unsigned char *result unsigned long orig_size = size; while (size) { - int len = 1+strlen(buffer); + size_t len = 1+strlen(buffer); convert_binary_sha1((char *) buffer + len); @@ -1399,7 +1399,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) return err; } } - s->size = st.st_size; + s->size = xsize_t(st.st_size); if (!s->size) goto empty; if (size_only) @@ -1515,12 +1515,13 @@ static void prepare_temp_file(const char *name, if (S_ISLNK(st.st_mode)) { int ret; char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */ + size_t sz = xsize_t(st.st_size); if (sizeof(buf) <= st.st_size) die("symlink too long: %s", name); - ret = readlink(name, buf, st.st_size); + ret = readlink(name, buf, sz); if (ret < 0) die("readlink(%s)", name); - prep_temp_blob(temp, buf, st.st_size, + prep_temp_blob(temp, buf, sz, (one->sha1_valid ? one->sha1 : null_sha1), (one->sha1_valid ? @@ -2138,7 +2139,7 @@ static int parse_num(const char **cp_p) /* user says num divided by scale and we say internally that * is MAX_SCORE * num / scale. */ - return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale); + return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale)); } int diff_scoreopt_parse(const char *opt) diff --git a/diffcore-break.c b/diffcore-break.c index acb18db1db..9c19b8cab7 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -89,7 +89,7 @@ static int should_break(struct diff_filespec *src, * merge the surviving pair together if the score is * less than the minimum, after rename/copy runs. */ - *merge_score_p = src_removed * MAX_SCORE / src->size; + *merge_score_p = (int)(src_removed * MAX_SCORE / src->size); /* Extent of damage, which counts both inserts and * deletes. diff --git a/diffcore-order.c b/diffcore-order.c index 7ad0946185..2a4bd8232e 100644 --- a/diffcore-order.c +++ b/diffcore-order.c @@ -14,6 +14,7 @@ static void prepare_order(const char *orderfile) void *map; char *cp, *endp; struct stat st; + size_t sz; if (order) return; @@ -25,11 +26,12 @@ static void prepare_order(const char *orderfile) close(fd); return; } - map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + sz = xsize_t(st.st_size); + map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) return; - endp = (char *) map + st.st_size; + endp = (char *) map + sz; for (pass = 0; pass < 2; pass++) { cnt = 0; cp = map; diff --git a/diffcore-rename.c b/diffcore-rename.c index 91fa2bea51..79030412db 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -172,7 +172,8 @@ static int estimate_similarity(struct diff_filespec *src, return 0; /* error but caught downstream */ - delta_limit = base_size * (MAX_SCORE-minimum_score) / MAX_SCORE; + delta_limit = (unsigned long) + (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE); if (diffcore_count_changes(src->data, src->size, dst->data, dst->size, &src->cnt_data, &dst->cnt_data, @@ -186,7 +187,7 @@ static int estimate_similarity(struct diff_filespec *src, if (!dst->size) score = 0; /* should not happen */ else - score = src_copied * MAX_SCORE / max_size; + score = (int)(src_copied * MAX_SCORE / max_size); return score; } @@ -297,7 +298,7 @@ void diffcore_rename(struct diff_options *options) struct diff_filespec *one = rename_src[j].one; if (!is_exact_match(one, two, contents_too)) continue; - record_rename_pair(i, j, MAX_SCORE); + record_rename_pair(i, j, (int)MAX_SCORE); rename_count++; break; /* we are done with this entry */ } @@ -130,13 +130,13 @@ static int add_excludes_from_file_1(const char *fname, { struct stat st; int fd, i; - long size; + size_t size; char *buf, *entry; fd = open(fname, O_RDONLY); if (fd < 0 || fstat(fd, &st) < 0) goto err; - size = st.st_size; + size = xsize_t(st.st_size); if (size == 0) { close(fd); return 0; diff --git a/environment.c b/environment.c index 49486dd9f1..0151ad0722 100644 --- a/environment.c +++ b/environment.c @@ -21,7 +21,7 @@ int log_all_ref_updates = -1; /* unspecified */ int warn_ambiguous_refs = 1; int repository_format_version; char *git_commit_encoding; -char *git_log_output_encoding; +const char *git_log_output_encoding; int shared_repository = PERM_UMASK; const char *apply_default_whitespace; int zlib_compression_level = Z_DEFAULT_COMPRESSION; diff --git a/fast-import.c b/fast-import.c index 65e99c2e8b..726f5ba7d2 100644 --- a/fast-import.c +++ b/fast-import.c @@ -133,10 +133,6 @@ Format of STDIN stream: #define PACK_ID_BITS 16 #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1) -#ifndef PRIuMAX -#define PRIuMAX "llu" -#endif - struct object_entry { struct object_entry *next; @@ -220,7 +216,8 @@ struct branch const char *name; struct tree_entry branch_tree; uintmax_t last_commit; - unsigned int pack_id; + unsigned active : 1; + unsigned pack_id : PACK_ID_BITS; unsigned char sha1[20]; }; @@ -252,7 +249,7 @@ typedef enum { /* Configured limits on output */ static unsigned long max_depth = 10; -static unsigned long max_packsize = (1LL << 32) - 1; +static off_t max_packsize = (1LL << 32) - 1; static int force_update; /* Stats and misc. counters */ @@ -528,6 +525,7 @@ static struct branch *new_branch(const char *name) b->table_next_branch = branch_table[hc]; b->branch_tree.versions[0].mode = S_IFDIR; b->branch_tree.versions[1].mode = S_IFDIR; + b->active = 0; b->pack_id = MAX_PACK_ID; branch_table[hc] = b; branch_count++; @@ -755,7 +753,7 @@ static char *create_index(void) static char *keep_pack(char *curr_index_name) { static char name[PATH_MAX]; - static char *keep_msg = "fast-import"; + static const char *keep_msg = "fast-import"; int keep_fd; chmod(pack_data->pack_name, 0444); @@ -1373,16 +1371,33 @@ static void dump_marks_helper(FILE *f, static void dump_marks(void) { - if (mark_file) - { - FILE *f = fopen(mark_file, "w"); - if (f) { - dump_marks_helper(f, 0, marks); - fclose(f); - } else - failure |= error("Unable to write marks file %s: %s", - mark_file, strerror(errno)); + static struct lock_file mark_lock; + int mark_fd; + FILE *f; + + if (!mark_file) + return; + + mark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0); + if (mark_fd < 0) { + failure |= error("Unable to write marks file %s: %s", + mark_file, strerror(errno)); + return; + } + + f = fdopen(mark_fd, "w"); + if (!f) { + rollback_lock_file(&mark_lock); + failure |= error("Unable to write marks file %s: %s", + mark_file, strerror(errno)); + return; } + + dump_marks_helper(f, 0, marks); + fclose(f); + if (commit_lock_file(&mark_lock)) + failure |= error("Unable to write marks file %s: %s", + mark_file, strerror(errno)); } static void read_next_command(void) @@ -1529,7 +1544,7 @@ static void unload_one_branch(void) { while (cur_active_branches && cur_active_branches >= max_active_branches) { - unsigned long min_commit = ULONG_MAX; + uintmax_t min_commit = ULONG_MAX; struct branch *e, *l = NULL, *p = NULL; for (e = active_branches; e; e = e->active_next_branch) { @@ -1547,6 +1562,7 @@ static void unload_one_branch(void) e = active_branches; active_branches = e->active_next_branch; } + e->active = 0; e->active_next_branch = NULL; if (e->branch_tree.tree) { release_tree_content_recursive(e->branch_tree.tree); @@ -1559,10 +1575,13 @@ static void unload_one_branch(void) static void load_branch(struct branch *b) { load_tree(&b->branch_tree); - b->active_next_branch = active_branches; - active_branches = b; - cur_active_branches++; - branch_load_count++; + if (!b->active) { + b->active = 1; + b->active_next_branch = active_branches; + active_branches = b; + cur_active_branches++; + branch_load_count++; + } } static void file_change_m(struct branch *b) @@ -1746,7 +1765,14 @@ static struct hash_list *cmd_merge(unsigned int *count) if (oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", idnum); hashcpy(n->sha1, oe->sha1); - } else if (get_sha1(from, n->sha1)) + } else if (!get_sha1(from, n->sha1)) { + unsigned long size; + char *buf = read_object_with_reference(n->sha1, + commit_type, &size, n->sha1); + if (!buf || size < 46) + die("Not a valid commit: %s", from); + free(buf); + } else die("Invalid ref name or SHA1 expression: %s", from); n->next = NULL; @@ -1967,6 +1993,40 @@ static void cmd_checkpoint(void) read_next_command(); } +static void import_marks(const char *input_file) +{ + char line[512]; + FILE *f = fopen(input_file, "r"); + if (!f) + die("cannot read %s: %s", input_file, strerror(errno)); + while (fgets(line, sizeof(line), f)) { + uintmax_t mark; + char *end; + unsigned char sha1[20]; + struct object_entry *e; + + end = strchr(line, '\n'); + if (line[0] != ':' || !end) + die("corrupt mark line: %s", line); + *end = 0; + mark = strtoumax(line + 1, &end, 10); + if (!mark || end == line + 1 + || *end != ' ' || get_sha1(end + 1, sha1)) + die("corrupt mark line: %s", line); + e = find_object(sha1); + if (!e) { + enum object_type type = sha1_object_info(sha1, NULL); + if (type < 0) + die("object not found: %s", sha1_to_hex(sha1)); + e = insert_object(sha1); + e->type = type; + e->pack_id = MAX_PACK_ID; + } + insert_mark(mark, e); + } + fclose(f); +} + static const char fast_import_usage[] = "git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]"; @@ -1975,6 +2035,12 @@ int main(int argc, const char **argv) int i, show_stats = 1; git_config(git_default_config); + alloc_objects(object_entry_alloc); + strbuf_init(&command_buf); + atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*)); + branch_table = xcalloc(branch_table_sz, sizeof(struct branch*)); + avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); + marks = pool_calloc(1, sizeof(struct mark_set)); for (i = 1; i < argc; i++) { const char *a = argv[i]; @@ -1998,6 +2064,8 @@ int main(int argc, const char **argv) max_depth = strtoul(a + 8, NULL, 0); else if (!prefixcmp(a, "--active-branches=")) max_active_branches = strtoul(a + 18, NULL, 0); + else if (!prefixcmp(a, "--import-marks=")) + import_marks(a + 15); else if (!prefixcmp(a, "--export-marks=")) mark_file = a + 15; else if (!prefixcmp(a, "--export-pack-edges=")) { @@ -2018,14 +2086,6 @@ int main(int argc, const char **argv) if (i != argc) usage(fast_import_usage); - alloc_objects(object_entry_alloc); - strbuf_init(&command_buf); - - atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*)); - branch_table = xcalloc(branch_table_sz, sizeof(struct branch*)); - avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); - marks = pool_calloc(1, sizeof(struct mark_set)); - start_packfile(); for (;;) { read_next_command(); diff --git a/git-archimport.perl b/git-archimport.perl index 0fcb156d14..c1e7c1ddcb 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -89,7 +89,11 @@ usage if $opt_h; # values associated with keys: # =1 - Arch version / git 'branch' detected via abrowse on a limit # >1 - Arch version / git 'branch' of an auxiliary branch we've merged -my %arch_branches = map { $_ => 1 } @ARGV; +my %arch_branches = map { my $branch = $_; $branch =~ s/:[^:]*$//; $branch => 1 } @ARGV; + +# $branch_name_map: +# maps arch branches to git branch names +my %branch_name_map = map { m/^(.*):([^:]*)$/; $1 => $2 } grep { m/:/ } @ARGV; $ENV{'TMPDIR'} = $opt_t if $opt_t; # $ENV{TMPDIR} will affect tempdir() calls: my $tmp = tempdir('git-archimport-XXXXXX', TMPDIR => 1, CLEANUP => 1); @@ -104,6 +108,7 @@ unless (-d $git_dir) { # initial import needs empty directory closedir DIR } +my $default_archive; # default Arch archive my %reachable = (); # Arch repositories we can access my %unreachable = (); # Arch repositories we can't access :< my @psets = (); # the collection @@ -303,7 +308,34 @@ sub old_style_branchname { return $ret; } -*git_branchname = $opt_o ? *old_style_branchname : *tree_dirname; +*git_default_branchname = $opt_o ? *old_style_branchname : *tree_dirname; + +# retrieve default archive, since $branch_name_map keys might not include it +sub get_default_archive { + if (!defined $default_archive) { + $default_archive = safe_pipe_capture($TLA,'my-default-archive'); + chomp $default_archive; + } + return $default_archive; +} + +sub git_branchname { + my $revision = shift; + my $name = extract_versionname($revision); + + if (exists $branch_name_map{$name}) { + return $branch_name_map{$name}; + + } elsif ($name =~ m#^([^/]*)/(.*)$# + && $1 eq get_default_archive() + && exists $branch_name_map{$2}) { + # the names given in the command-line lacked the archive. + return $branch_name_map{$2}; + + } else { + return git_default_branchname($revision); + } +} sub process_patchset_accurate { my $ps = shift; @@ -333,19 +365,23 @@ sub process_patchset_accurate { if ($ps->{tag} && (my $branchpoint = eval { ptag($ps->{tag}) })) { # find where we are supposed to branch from - system('git-checkout','-f','-b',$ps->{branch}, - $branchpoint) == 0 or die "$! $?\n"; - + if (! -e "$git_dir/refs/heads/$ps->{branch}") { + system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; + + # We trust Arch with the fact that this is just a tag, + # and it does not affect the state of the tree, so + # we just tag and move on. If the user really wants us + # to consolidate more branches into one, don't tag because + # the tag name would be already taken. + tag($ps->{id}, $branchpoint); + ptag($ps->{id}, $branchpoint); + print " * Tagged $ps->{id} at $branchpoint\n"; + } + system('git-checkout','-f',$ps->{branch}) == 0 or die "$! $?\n"; + # remove any old stuff that got leftover: my $rm = safe_pipe_capture('git-ls-files','--others','-z'); rmtree(split(/\0/,$rm)) if $rm; - - # If we trust Arch with the fact that this is just - # a tag, and it does not affect the state of the tree - # then we just tag and move on - tag($ps->{id}, $branchpoint); - ptag($ps->{id}, $branchpoint); - print " * Tagged $ps->{id} at $branchpoint\n"; return 0; } else { warn "Tagging from unknown id unsupported\n" if $ps->{tag}; @@ -385,14 +421,19 @@ sub process_patchset_fast { unless $branchpoint; # find where we are supposed to branch from - system('git-checkout','-b',$ps->{branch},$branchpoint); - - # If we trust Arch with the fact that this is just - # a tag, and it does not affect the state of the tree - # then we just tag and move on - tag($ps->{id}, $branchpoint); - ptag($ps->{id}, $branchpoint); - print " * Tagged $ps->{id} at $branchpoint\n"; + if (! -e "$git_dir/refs/heads/$ps->{branch}") { + system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; + + # We trust Arch with the fact that this is just a tag, + # and it does not affect the state of the tree, so + # we just tag and move on. If the user really wants us + # to consolidate more branches into one, don't tag because + # the tag name would be already taken. + tag($ps->{id}, $branchpoint); + ptag($ps->{id}, $branchpoint); + print " * Tagged $ps->{id} at $branchpoint\n"; + } + system('git-checkout',$ps->{branch}) == 0 or die "$! $?\n"; return 0; } die $! if $?; @@ -830,8 +871,9 @@ sub tag { if ($opt_o) { $tag =~ s|/|--|g; } else { - # don't use subdirs for tags yet, it could screw up other porcelains - $tag =~ s|/|,|g; + my $patchname = $tag; + $patchname =~ s/.*--//; + $tag = git_branchname ($tag) . '--' . $patchname; } if ($commit) { diff --git a/git-commit.sh b/git-commit.sh index be3677c204..3656d607d5 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Linus Torvalds # Copyright (c) 2006 Junio C Hamano -USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]' +USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]' SUBDIRECTORY_OK=Yes . git-sh-setup require_work_tree @@ -71,6 +71,7 @@ trap ' all= also= +interactive= only= logfile= use_commit= @@ -131,6 +132,11 @@ do also=t shift ;; + --int|--inte|--inter|--intera|--interac|--interact|--interacti|\ + --interactiv|--interactive) + interactive=t + shift + ;; -o|--o|--on|--onl|--only) only=t shift @@ -304,12 +310,14 @@ case "$#,$also,$only,$amend" in ;; esac unset only -case "$all,$also,$#" in -t,t,*) - die "Cannot use -a and -i at the same time." ;; +case "$all,$interactive,$also,$#" in +*t,*t,*) + die "Cannot use -a, --interactive or -i at the same time." ;; t,,[1-9]*) die "Paths with -a does not make sense." ;; -,t,0) +,t,[1-9]*) + die "Paths with --interactive does not make sense." ;; +,,t,0) die "No paths with -i does not make sense." ;; esac @@ -344,6 +352,9 @@ t,) ) || exit ;; ,) + if test "$interactive" = t; then + git add --interactive || exit + fi case "$#" in 0) ;; # commit as-is @@ -622,6 +633,9 @@ else fi ret="$?" rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG" + +cd_to_toplevel + if test -d "$GIT_DIR/rr-cache" then git-rerere diff --git a/git-compat-util.h b/git-compat-util.h index 56212b2f11..7534db1267 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -70,6 +70,10 @@ #define PATH_MAX 4096 #endif +#ifndef PRIuMAX +#define PRIuMAX "llu" +#endif + #ifdef __GNUC__ #define NORETURN __attribute__((__noreturn__)) #else @@ -254,6 +258,11 @@ static inline ssize_t xwrite(int fd, const void *buf, size_t len) } } +static inline size_t xsize_t(off_t len) +{ + return (size_t)len; +} + static inline int has_extension(const char *filename, const char *ext) { size_t len = strlen(filename); diff --git a/git-gui/Makefile b/git-gui/Makefile index 66538ba1ad..e486e8f984 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -1,5 +1,8 @@ all:: +# Define V=1 to have a more verbose compile. +# + GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN -include GIT-VERSION-FILE @@ -19,27 +22,32 @@ ifndef INSTALL INSTALL = install endif +ifndef V + QUIET_GEN = @echo ' ' GEN $@; + QUIET_BUILT_IN = @echo ' ' BUILTIN $@; +endif + DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) git-gui: git-gui.sh GIT-VERSION-FILE CREDITS-FILE - rm -f $@ $@+ + $(QUIET_GEN)rm -f $@ $@+ && \ sed -n \ -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ -e '1,/^set gitgui_credits /p' \ - $@.sh >$@+ - cat CREDITS-FILE >>$@+ - sed -e '1,/^set gitgui_credits /d' $@.sh >>$@+ - chmod +x $@+ + $@.sh >$@+ && \ + cat CREDITS-FILE >>$@+ && \ + sed -e '1,/^set gitgui_credits /d' $@.sh >>$@+ && \ + chmod +x $@+ && \ mv $@+ $@ CREDITS-FILE: CREDITS-GEN .FORCE-CREDITS-FILE - $(SHELL_PATH) ./CREDITS-GEN + $(QUIET_GEN)$(SHELL_PATH) ./CREDITS-GEN $(GITGUI_BUILT_INS): git-gui - rm -f $@ && ln git-gui $@ + $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ all:: $(ALL_PROGRAMS) diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index f84ba3382b..1981827a8e 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -1267,6 +1267,24 @@ proc commit_committree {fd_wt curHEAD msg} { return } + # -- Verify this wasn't an empty change. + # + if {$commit_type eq {normal}} { + set old_tree [git rev-parse "$PARENT^{tree}"] + if {$tree_id eq $old_tree} { + info_popup {No changes to commit. + +No files were modified by this commit and it +was not a merge commit. + +A rescan will be automatically started now. +} + unlock_index + rescan {set ui_status_value {No changes to commit.}} + return + } + } + # -- Build the message. # set msg_p [gitdir COMMIT_EDITMSG] @@ -1281,14 +1299,8 @@ proc commit_committree {fd_wt curHEAD msg} { # -- Create the commit. # set cmd [list git commit-tree $tree_id] - set parents [concat $PARENT $MERGE_HEAD] - if {[llength $parents] > 0} { - foreach p $parents { - lappend cmd -p $p - } - } else { - # git commit-tree writes to stderr during initial commit. - lappend cmd 2>/dev/null + foreach p [concat $PARENT $MERGE_HEAD] { + lappend cmd -p $p } lappend cmd <$msg_p if {[catch {set cmt_id [eval exec $cmd]} err]} { @@ -5256,6 +5268,12 @@ if {[is_enabled branch]} { -font font_ui lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] + + .mbar.branch add command -label {Reset...} \ + -command do_reset_hard \ + -font font_ui + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] } # -- Commit Menu @@ -5330,6 +5348,34 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { [list .mbar.commit entryconf [.mbar.commit index last] -state] } +# -- Merge Menu +# +if {[is_enabled branch]} { + menu .mbar.merge + .mbar.merge add command -label {Local Merge...} \ + -command do_local_merge \ + -font font_ui + lappend disable_on_lock \ + [list .mbar.merge entryconf [.mbar.merge index last] -state] + .mbar.merge add command -label {Abort Merge...} \ + -command do_reset_hard \ + -font font_ui + lappend disable_on_lock \ + [list .mbar.merge entryconf [.mbar.merge index last] -state] + +} + +# -- Transport Menu +# +if {[is_enabled transport]} { + menu .mbar.fetch + + menu .mbar.push + .mbar.push add command -label {Push...} \ + -command do_push_anywhere \ + -font font_ui +} + if {[is_MacOSX]} { # -- Apple Menu (Mac OS X only) # @@ -5502,28 +5548,6 @@ pack .branch.l1 -side left pack .branch.cb -side left -fill x pack .branch -side top -fill x -if {[is_enabled branch]} { - menu .mbar.merge - .mbar.merge add command -label {Local Merge...} \ - -command do_local_merge \ - -font font_ui - lappend disable_on_lock \ - [list .mbar.merge entryconf [.mbar.merge index last] -state] - .mbar.merge add command -label {Abort Merge...} \ - -command do_reset_hard \ - -font font_ui - lappend disable_on_lock \ - [list .mbar.merge entryconf [.mbar.merge index last] -state] - - - menu .mbar.fetch - - menu .mbar.push - .mbar.push add command -label {Push...} \ - -command do_push_anywhere \ - -font font_ui -} - # -- Main Window Layout # panedwindow .vpane -orient vertical diff --git a/git-revert.sh b/git-revert.sh deleted file mode 100755 index 49f00321b2..0000000000 --- a/git-revert.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Linus Torvalds -# Copyright (c) 2005 Junio C Hamano -# - -case "$0" in -*-revert* ) - test -t 0 && edit=-e - replay= - me=revert - USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;; -*-cherry-pick* ) - replay=t - edit= - me=cherry-pick - USAGE='[--edit] [-n] [-r] [-x] <commit-ish>' ;; -* ) - echo >&2 "What are you talking about?" - exit 1 ;; -esac - -SUBDIRECTORY_OK=Yes ;# we will cd up -. git-sh-setup -require_work_tree -cd_to_toplevel - -no_commit= -while case "$#" in 0) break ;; esac -do - case "$1" in - -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\ - --no-commi|--no-commit) - no_commit=t - ;; - -e|--e|--ed|--edi|--edit) - edit=-e - ;; - --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit) - edit= - ;; - -r) - : no-op ;; - -x|--i-really-want-to-expose-my-private-commit-object-name) - replay= - ;; - -*) - usage - ;; - *) - break - ;; - esac - shift -done - -set_reflog_action "$me" - -test "$me,$replay" = "revert,t" && usage - -case "$no_commit" in -t) - # We do not intend to commit immediately. We just want to - # merge the differences in. - head=$(git-write-tree) || - die "Your index file is unmerged." - ;; -*) - head=$(git-rev-parse --verify HEAD) || - die "You do not have a valid HEAD" - files=$(git-diff-index --cached --name-only $head) || exit - if [ "$files" ]; then - die "Dirty index: cannot $me (dirty: $files)" - fi - ;; -esac - -rev=$(git-rev-parse --verify "$@") && -commit=$(git-rev-parse --verify "$rev^0") || - die "Not a single commit $@" -prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) || - die "Cannot run $me a root commit" -git-rev-parse --verify "$commit^2" >/dev/null 2>&1 && - die "Cannot run $me a multi-parent commit." - -encoding=$(git config i18n.commitencoding || echo UTF-8) - -# "commit" is an existing commit. We would want to apply -# the difference it introduces since its first parent "prev" -# on top of the current HEAD if we are cherry-pick. Or the -# reverse of it if we are revert. - -case "$me" in -revert) - git show -s --pretty=oneline --encoding="$encoding" $commit | - sed -e ' - s/^[^ ]* /Revert "/ - s/$/"/ - ' - echo - echo "This reverts commit $commit." - test "$rev" = "$commit" || - echo "(original 'git revert' arguments: $@)" - base=$commit next=$prev - ;; - -cherry-pick) - pick_author_script=' - /^author /{ - s/'\''/'\''\\'\'\''/g - h - s/^author \([^<]*\) <[^>]*> .*$/\1/ - s/'\''/'\''\'\'\''/g - s/.*/GIT_AUTHOR_NAME='\''&'\''/p - - g - s/^author [^<]* <\([^>]*\)> .*$/\1/ - s/'\''/'\''\'\'\''/g - s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p - - g - s/^author [^<]* <[^>]*> \(.*\)$/\1/ - s/'\''/'\''\'\'\''/g - s/.*/GIT_AUTHOR_DATE='\''&'\''/p - - q - }' - - logmsg=`git show -s --pretty=raw --encoding="$encoding" "$commit"` - set_author_env=`echo "$logmsg" | - LANG=C LC_ALL=C sed -ne "$pick_author_script"` - eval "$set_author_env" - export GIT_AUTHOR_NAME - export GIT_AUTHOR_EMAIL - export GIT_AUTHOR_DATE - - echo "$logmsg" | - sed -e '1,/^$/d' -e 's/^ //' - case "$replay" in - '') - echo "(cherry picked from commit $commit)" - test "$rev" = "$commit" || - echo "(original 'git cherry-pick' arguments: $@)" - ;; - esac - base=$prev next=$commit - ;; - -esac >.msg - -eval GITHEAD_$head=HEAD -eval GITHEAD_$next='`git show -s \ - --pretty=oneline --encoding="$encoding" "$commit" | - sed -e "s/^[^ ]* //"`' -export GITHEAD_$head GITHEAD_$next - -# This three way merge is an interesting one. We are at -# $head, and would want to apply the change between $commit -# and $prev on top of us (when reverting), or the change between -# $prev and $commit on top of us (when cherry-picking or replaying). - -git-merge-recursive $base -- $head $next && -result=$(git-write-tree 2>/dev/null) || { - mv -f .msg "$GIT_DIR/MERGE_MSG" - { - echo ' -Conflicts: -' - git ls-files --unmerged | - sed -e 's/^[^ ]* / /' | - uniq - } >>"$GIT_DIR/MERGE_MSG" - echo >&2 "Automatic $me failed. After resolving the conflicts," - echo >&2 "mark the corrected paths with 'git-add <paths>'" - echo >&2 "and commit the result." - case "$me" in - cherry-pick) - echo >&2 "You may choose to use the following when making" - echo >&2 "the commit:" - echo >&2 "$set_author_env" - esac - exit 1 -} -echo >&2 "Finished one $me." - -# If we are cherry-pick, and if the merge did not result in -# hand-editing, we will hit this commit and inherit the original -# author date and name. -# If we are revert, or if our cherry-pick results in a hand merge, -# we had better say that the current user is responsible for that. - -case "$no_commit" in -'') - git-commit -n -F .msg $edit - rm -f .msg - ;; -esac @@ -234,6 +234,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "checkout-index", cmd_checkout_index, RUN_SETUP }, { "check-ref-format", cmd_check_ref_format }, { "cherry", cmd_cherry, RUN_SETUP }, + { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NOT_BARE }, { "commit-tree", cmd_commit_tree, RUN_SETUP }, { "config", cmd_config }, { "count-objects", cmd_count_objects, RUN_SETUP }, @@ -272,6 +273,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "rerere", cmd_rerere, RUN_SETUP }, { "rev-list", cmd_rev_list, RUN_SETUP }, { "rev-parse", cmd_rev_parse, RUN_SETUP }, + { "revert", cmd_revert, RUN_SETUP | NOT_BARE }, { "rm", cmd_rm, RUN_SETUP | NOT_BARE }, { "runstatus", cmd_runstatus, RUN_SETUP | NOT_BARE }, { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER }, diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 653ca3cc60..27b5970bca 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -591,7 +591,7 @@ sub esc_html ($;%) { my %opts = @_; $str = to_utf8($str); - $str = escapeHTML($str); + $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; } @@ -605,7 +605,7 @@ sub esc_path { my %opts = @_; $str = to_utf8($str); - $str = escapeHTML($str); + $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; } @@ -1974,17 +1974,17 @@ sub git_print_page_path { $fullname .= ($fullname ? '/' : '') . $dir; print $cgi->a({-href => href(action=>"tree", file_name=>$fullname, hash_base=>$hb), - -title => esc_html($fullname)}, esc_path($dir)); + -title => $fullname}, esc_path($dir)); print " / "; } if (defined $type && $type eq 'blob') { print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name, hash_base=>$hb), - -title => esc_html($name)}, esc_path($basename)); + -title => $name}, esc_path($basename)); } elsif (defined $type && $type eq 'tree') { print $cgi->a({-href => href(action=>"tree", file_name=>$file_name, hash_base=>$hb), - -title => esc_html($name)}, esc_path($basename)); + -title => $name}, esc_path($basename)); print " / "; } else { print esc_path($basename); diff --git a/index-pack.c b/index-pack.c index cf81a99500..b405864be9 100644 --- a/index-pack.c +++ b/index-pack.c @@ -753,7 +753,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, const char *keep_name, const char *keep_msg, unsigned char *sha1) { - char *report = "pack"; + const char *report = "pack"; char name[PATH_MAX]; int err; diff --git a/interpolate.c b/interpolate.c index f992ef7753..fb30694f47 100644 --- a/interpolate.c +++ b/interpolate.c @@ -55,7 +55,7 @@ int interpolate(char *result, int reslen, const char *src = orig; char *dest = result; int newlen = 0; - char *name, *value; + const char *name, *value; int namelen, valuelen; int i; char c; diff --git a/interpolate.h b/interpolate.h index 190a180b58..16a26b9986 100644 --- a/interpolate.h +++ b/interpolate.h @@ -12,7 +12,7 @@ */ struct interp { - char *name; + const char *name; char *value; }; diff --git a/pack-check.c b/pack-check.c index f248ac8c7a..299c514128 100644 --- a/pack-check.c +++ b/pack-check.c @@ -4,12 +4,13 @@ static int verify_packfile(struct packed_git *p, struct pack_window **w_curs) { - unsigned long index_size = p->index_size; + off_t index_size = p->index_size; void *index_base = p->index_base; SHA_CTX ctx; unsigned char sha1[20]; - unsigned long offset = 0, pack_sig = p->pack_size - 20; - int nr_objects, err, i; + off_t offset = 0, pack_sig = p->pack_size - 20; + uint32_t nr_objects, i; + int err; /* Note that the pack header checks are actually performed by * use_pack when it first opens the pack file. If anything @@ -23,7 +24,7 @@ static int verify_packfile(struct packed_git *p, unsigned char *in = use_pack(p, w_curs, offset, &remaining); offset += remaining; if (offset > pack_sig) - remaining -= offset - pack_sig; + remaining -= (unsigned int)(offset - pack_sig); SHA1_Update(&ctx, in, remaining); } SHA1_Final(sha1, &ctx); @@ -40,11 +41,12 @@ static int verify_packfile(struct packed_git *p, * we do not do scan-streaming check on the pack file. */ nr_objects = num_packed_objects(p); - for (i = err = 0; i < nr_objects; i++) { + for (i = 0, err = 0; i < nr_objects; i++) { unsigned char sha1[20]; void *data; enum object_type type; - unsigned long size, offset; + unsigned long size; + off_t offset; if (nth_packed_object_sha1(p, i, sha1)) die("internal error pack-check nth-packed-object"); @@ -74,8 +76,7 @@ static int verify_packfile(struct packed_git *p, static void show_pack_info(struct packed_git *p) { - int nr_objects, i; - unsigned int chain_histogram[MAX_CHAIN]; + uint32_t nr_objects, i, chain_histogram[MAX_CHAIN]; nr_objects = num_packed_objects(p); memset(chain_histogram, 0, sizeof(chain_histogram)); @@ -85,7 +86,7 @@ static void show_pack_info(struct packed_git *p) const char *type; unsigned long size; unsigned long store_size; - unsigned long offset; + off_t offset; unsigned int delta_chain_length; if (nth_packed_object_sha1(p, i, sha1)) @@ -99,9 +100,11 @@ static void show_pack_info(struct packed_git *p) base_sha1); printf("%s ", sha1_to_hex(sha1)); if (!delta_chain_length) - printf("%-6s %lu %lu\n", type, size, offset); + printf("%-6s %lu %"PRIuMAX"\n", + type, size, (uintmax_t)offset); else { - printf("%-6s %lu %lu %u %s\n", type, size, offset, + printf("%-6s %lu %"PRIuMAX" %u %s\n", + type, size, (uintmax_t)offset, delta_chain_length, sha1_to_hex(base_sha1)); if (delta_chain_length < MAX_CHAIN) chain_histogram[delta_chain_length]++; @@ -123,7 +126,7 @@ static void show_pack_info(struct packed_git *p) int verify_pack(struct packed_git *p, int verbose) { - unsigned long index_size = p->index_size; + off_t index_size = p->index_size; void *index_base = p->index_base; SHA_CTX ctx; unsigned char sha1[20]; @@ -132,7 +135,7 @@ int verify_pack(struct packed_git *p, int verbose) ret = 0; /* Verify SHA1 sum of the index file */ SHA1_Init(&ctx); - SHA1_Update(&ctx, index_base, index_size - 20); + SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20)); SHA1_Final(sha1, &ctx); if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20)) ret = error("Packfile index for %s SHA1 mismatch", diff --git a/pack-redundant.c b/pack-redundant.c index edb5524fc4..c8f7d9af7b 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -396,9 +396,9 @@ static size_t get_pack_redundancy(struct pack_list *pl) return ret; } -static inline size_t pack_set_bytecount(struct pack_list *pl) +static inline off_t pack_set_bytecount(struct pack_list *pl) { - size_t ret = 0; + off_t ret = 0; while (pl) { ret += pl->pack->pack_size; ret += pl->pack->index_size; @@ -413,7 +413,7 @@ static void minimize(struct pack_list **min) *non_unique = NULL, *min_perm = NULL; struct pll *perm, *perm_all, *perm_ok = NULL, *new_perm; struct llist *missing; - size_t min_perm_size = (size_t)-1, perm_size; + off_t min_perm_size = 0, perm_size; int n; pl = local_packs; @@ -461,7 +461,7 @@ static void minimize(struct pack_list **min) perm = perm_ok; while (perm) { perm_size = pack_set_bytecount(perm->pl); - if (min_perm_size > perm_size) { + if (!min_perm_size || min_perm_size > perm_size) { min_perm_size = perm_size; min_perm = perm->pl; } @@ -252,7 +252,7 @@ char *enter_repo(char *path, int strict) if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 && validate_headref("HEAD") == 0) { - putenv("GIT_DIR=."); + setenv("GIT_DIR", ".", 1); check_repository_format(); return path; } diff --git a/perl/Makefile b/perl/Makefile index 099beda873..5ec0389883 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -6,11 +6,15 @@ makfile:=perl.mak PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) prefix_SQ = $(subst ','\'',$(prefix)) +ifndef V + QUIET = @ +endif + all install instlibdir: $(makfile) - $(MAKE) -f $(makfile) $@ + $(QUIET)$(MAKE) -f $(makfile) $@ clean: - test -f $(makfile) && $(MAKE) -f $(makfile) $@ || exit 0 + $(QUIET)test -f $(makfile) && $(MAKE) -f $(makfile) $@ || exit 0 $(RM) ppport.h $(RM) $(makfile) $(RM) $(makfile).old @@ -29,7 +33,7 @@ $(makfile): ../GIT-CFLAGS Makefile echo ' echo $(instdir_SQ)' >> $@ else $(makfile): Makefile.PL ../GIT-CFLAGS - '$(PERL_PATH_SQ)' $< PREFIX='$(prefix_SQ)' + $(QUIET_GEN)'$(PERL_PATH_SQ)' $< PREFIX='$(prefix_SQ)' endif # this is just added comfort for calling make directly in perl dir diff --git a/read-cache.c b/read-cache.c index 4a972b4ab7..6339a278da 100644 --- a/read-cache.c +++ b/read-cache.c @@ -66,7 +66,7 @@ static int ce_compare_data(struct cache_entry *ce, struct stat *st) return match; } -static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size) +static int ce_compare_link(struct cache_entry *ce, size_t expected_size) { int match = -1; char *target; @@ -101,7 +101,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st) return DATA_CHANGED; break; case S_IFLNK: - if (ce_compare_link(ce, st->st_size)) + if (ce_compare_link(ce, xsize_t(st->st_size))) return DATA_CHANGED; break; default: @@ -797,7 +797,7 @@ int read_cache_from(const char *path) } if (!fstat(fd, &st)) { - cache_mmap_size = st.st_size; + cache_mmap_size = xsize_t(st.st_size); errno = EINVAL; if (cache_mmap_size >= sizeof(struct cache_header) + 20) cache_mmap = xmmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); diff --git a/receive-pack.c b/receive-pack.c index 7f1dcc045c..675c88f492 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -67,18 +67,47 @@ struct command { static struct command *commands; -static char update_hook[] = "hooks/update"; +static const char update_hook[] = "hooks/update"; +static const char pre_receive_hook[] = "hooks/pre-receive"; +static const char post_receive_hook[] = "hooks/post-receive"; -static int run_update_hook(const char *refname, - char *old_hex, char *new_hex) +static int run_hook(const char *hook_name, + struct command *first_cmd, + int single) { - int code; + struct command *cmd; + int argc, code; + const char **argv; - if (access(update_hook, X_OK) < 0) + for (argc = 0, cmd = first_cmd; cmd; cmd = cmd->next) { + if (!cmd->error_string) + argc += 3; + if (single) + break; + } + + if (!argc || access(hook_name, X_OK) < 0) return 0; - code = run_command_opt(RUN_COMMAND_NO_STDIN - | RUN_COMMAND_STDOUT_TO_STDERR, - update_hook, refname, old_hex, new_hex, NULL); + + argv = xmalloc(sizeof(*argv) * (2 + argc)); + argv[0] = hook_name; + for (argc = 1, cmd = first_cmd; cmd; cmd = cmd->next) { + if (!cmd->error_string) { + argv[argc++] = xstrdup(cmd->ref_name); + argv[argc++] = xstrdup(sha1_to_hex(cmd->old_sha1)); + argv[argc++] = xstrdup(sha1_to_hex(cmd->new_sha1)); + } + if (single) + break; + } + argv[argc] = NULL; + + code = run_command_v_opt(argv, + RUN_COMMAND_NO_STDIN | RUN_COMMAND_STDOUT_TO_STDERR); + while (--argc > 0) + free((char*)argv[argc]); + free(argv); + switch (code) { case 0: return 0; @@ -91,37 +120,31 @@ static int run_update_hook(const char *refname, case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: return error("waitpid is confused"); case -ERR_RUN_COMMAND_WAITPID_SIGNAL: - return error("%s died of signal", update_hook); + return error("%s died of signal", hook_name); case -ERR_RUN_COMMAND_WAITPID_NOEXIT: - return error("%s died strangely", update_hook); + return error("%s died strangely", hook_name); default: - error("%s exited with error code %d", update_hook, -code); + error("%s exited with error code %d", hook_name, -code); return -code; } } -static int update(struct command *cmd) +static const char *update(struct command *cmd) { const char *name = cmd->ref_name; unsigned char *old_sha1 = cmd->old_sha1; unsigned char *new_sha1 = cmd->new_sha1; - char new_hex[41], old_hex[41]; struct ref_lock *lock; - cmd->error_string = NULL; if (!prefixcmp(name, "refs/") && check_ref_format(name + 5)) { - cmd->error_string = "funny refname"; - return error("refusing to create funny ref '%s' locally", - name); + error("refusing to create funny ref '%s' locally", name); + return "funny refname"; } - strcpy(new_hex, sha1_to_hex(new_sha1)); - strcpy(old_hex, sha1_to_hex(old_sha1)); - if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) { - cmd->error_string = "bad pack"; - return error("unpack should have generated %s, " - "but I can't find it!", new_hex); + error("unpack should have generated %s, " + "but I can't find it!", sha1_to_hex(new_sha1)); + return "bad pack"; } if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && !is_null_sha1(old_sha1) && @@ -136,32 +159,39 @@ static int update(struct command *cmd) if (!hashcmp(old_sha1, ent->item->object.sha1)) break; free_commit_list(bases); - if (!ent) - return error("denying non-fast forward;" - " you should pull first"); + if (!ent) { + error("denying non-fast forward %s" + " (you should pull first)", name); + return "non-fast forward"; + } } - if (run_update_hook(name, old_hex, new_hex)) { - cmd->error_string = "hook declined"; - return error("hook declined to update %s", name); + if (run_hook(update_hook, cmd, 1)) { + error("hook declined to update %s", name); + return "hook declined"; } if (is_null_sha1(new_sha1)) { if (delete_ref(name, old_sha1)) { - cmd->error_string = "failed to delete"; - return error("failed to delete %s", name); + error("failed to delete %s", name); + return "failed to delete"; } - fprintf(stderr, "%s: %s -> deleted\n", name, old_hex); + fprintf(stderr, "%s: %s -> deleted\n", name, + sha1_to_hex(old_sha1)); + return NULL; /* good */ } else { lock = lock_any_ref_for_update(name, old_sha1); if (!lock) { - cmd->error_string = "failed to lock"; - return error("failed to lock %s", name); + error("failed to lock %s", name); + return "failed to lock"; + } + if (write_ref_sha1(lock, new_sha1, "push")) { + return "failed to write"; /* error() already called */ } - write_ref_sha1(lock, new_sha1, "push"); - fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex); + fprintf(stderr, "%s: %s -> %s\n", name, + sha1_to_hex(old_sha1), sha1_to_hex(new_sha1)); + return NULL; /* good */ } - return 0; } static char update_post_hook[] = "hooks/post-update"; @@ -172,14 +202,14 @@ static void run_update_post_hook(struct command *cmd) int argc; const char **argv; - if (access(update_post_hook, X_OK) < 0) - return; - for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) { + for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) { if (cmd_p->error_string) continue; argc++; } - argv = xmalloc(sizeof(*argv) * (1 + argc)); + if (!argc || access(update_post_hook, X_OK) < 0) + return; + argv = xmalloc(sizeof(*argv) * (2 + argc)); argv[0] = update_post_hook; for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) { @@ -196,19 +226,30 @@ static void run_update_post_hook(struct command *cmd) | RUN_COMMAND_STDOUT_TO_STDERR); } -/* - * This gets called after(if) we've successfully - * unpacked the data payload. - */ -static void execute_commands(void) +static void execute_commands(const char *unpacker_error) { struct command *cmd = commands; + if (unpacker_error) { + while (cmd) { + cmd->error_string = "n/a (unpacker error)"; + cmd = cmd->next; + } + return; + } + + if (run_hook(pre_receive_hook, commands, 0)) { + while (cmd) { + cmd->error_string = "pre-receive hook declined"; + cmd = cmd->next; + } + return; + } + while (cmd) { - update(cmd); + cmd->error_string = update(cmd); cmd = cmd->next; } - run_update_post_hook(commands); } static void read_head_info(void) @@ -244,7 +285,7 @@ static void read_head_info(void) hashcpy(cmd->old_sha1, old_sha1); hashcpy(cmd->new_sha1, new_sha1); memcpy(cmd->ref_name, line + 82, len - 81); - cmd->error_string = "n/a (unpacker error)"; + cmd->error_string = NULL; cmd->next = NULL; *p = cmd; p = &cmd->next; @@ -447,12 +488,13 @@ int main(int argc, char **argv) if (!delete_only(commands)) unpack_status = unpack(); - if (!unpack_status) - execute_commands(); + execute_commands(unpack_status); if (pack_lockfile) unlink(pack_lockfile); if (report_status) report(unpack_status); + run_hook(post_receive_hook, commands, 0); + run_update_post_hook(commands); } return 0; } @@ -921,6 +921,8 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, log_file, strerror(errno)); } + adjust_shared_perm(log_file); + msglen = 0; if (msg) { /* clean up the message and make sure it is a single line */ @@ -1075,6 +1077,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * unsigned long date; unsigned char logged_sha1[20]; void *log_mapped; + size_t mapsz; logfile = git_path("logs/%s", ref); logfd = open(logfile, O_RDONLY, 0); @@ -1083,7 +1086,8 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * fstat(logfd, &st); if (!st.st_size) die("Log %s is empty.", logfile); - log_mapped = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0); + mapsz = xsize_t(st.st_size); + log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0); logdata = log_mapped; close(logfd); @@ -1136,7 +1140,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * logfile, show_rfc2822_date(date, tz)); } } - munmap(log_mapped, st.st_size); + munmap(log_mapped, mapsz); return 0; } lastrec = rec; @@ -1155,7 +1159,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * die("Log %s is corrupt.", logfile); if (msg) *msg = ref_msg(logdata, logend); - munmap(log_mapped, st.st_size); + munmap(log_mapped, mapsz); if (cutoff_time) *cutoff_time = date; @@ -216,7 +216,7 @@ const char *setup_git_directory_gently(int *nongit_ok) die("Not a git repository: '%s'", gitdirenv); } - if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/') + if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/') die("Unable to read current working directory"); offset = len = strlen(cwd); diff --git a/sha1_file.c b/sha1_file.c index ac6b5e00b6..7faa8bcd50 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -349,6 +349,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, static void read_info_alternates(const char * relative_base, int depth) { char *map; + size_t mapsz; struct stat st; char path[PATH_MAX]; int fd; @@ -361,12 +362,13 @@ static void read_info_alternates(const char * relative_base, int depth) close(fd); return; } - map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + mapsz = xsize_t(st.st_size); + map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); - link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth); + link_alt_odb_entries(map, map + mapsz, '\n', relative_base, depth); - munmap(map, st.st_size); + munmap(map, mapsz); } void prepare_alt_odb(void) @@ -430,13 +432,14 @@ void pack_report() pack_mapped, peak_pack_mapped); } -static int check_packed_git_idx(const char *path, unsigned long *idx_size_, - void **idx_map_) +static int check_packed_git_idx(const char *path, + unsigned long *idx_size_, + void **idx_map_) { void *idx_map; uint32_t *index; - unsigned long idx_size; - int nr, i; + size_t idx_size; + uint32_t nr, i; int fd = open(path, O_RDONLY); struct stat st; if (fd < 0) @@ -445,7 +448,11 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_, close(fd); return -1; } - idx_size = st.st_size; + idx_size = xsize_t(st.st_size); + if (idx_size < 4 * 256 + 20 + 20) { + close(fd); + return error("index file %s is too small", path); + } idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); @@ -453,25 +460,25 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_, *idx_map_ = idx_map; *idx_size_ = idx_size; - /* check index map */ - if (idx_size < 4*256 + 20 + 20) - return error("index file %s is too small", path); - /* a future index format would start with this, as older git * binaries would fail the non-monotonic index check below. * give a nicer warning to the user if we can. */ - if (index[0] == htonl(PACK_IDX_SIGNATURE)) + if (index[0] == htonl(PACK_IDX_SIGNATURE)) { + munmap(idx_map, idx_size); return error("index file %s is a newer version" " and is not supported by this binary" " (try upgrading GIT to a newer version)", path); + } nr = 0; for (i = 0; i < 256; i++) { - unsigned int n = ntohl(index[i]); - if (n < nr) + uint32_t n = ntohl(index[i]); + if (n < nr) { + munmap(idx_map, idx_size); return error("non-monotonic index %s", path); + } nr = n; } @@ -482,8 +489,10 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_, * - 20-byte SHA1 of the packfile * - 20-byte SHA1 file checksum */ - if (idx_size != 4*256 + nr * 24 + 20 + 20) + if (idx_size != 4*256 + nr * 24 + 20 + 20) { + munmap(idx_map, idx_size); return error("wrong index file size in %s", path); + } return 0; } @@ -622,7 +631,7 @@ static int open_packed_git(struct packed_git *p) return -1; } -static int in_window(struct pack_window *win, unsigned long offset) +static int in_window(struct pack_window *win, off_t offset) { /* We must promise at least 20 bytes (one hash) after the * offset is available from this window, otherwise the offset @@ -637,7 +646,7 @@ static int in_window(struct pack_window *win, unsigned long offset) unsigned char* use_pack(struct packed_git *p, struct pack_window **w_cursor, - unsigned long offset, + off_t offset, unsigned int *left) { struct pack_window *win = *w_cursor; @@ -662,11 +671,13 @@ unsigned char* use_pack(struct packed_git *p, } if (!win) { size_t window_align = packed_git_window_size / 2; + off_t len; win = xcalloc(1, sizeof(*win)); win->offset = (offset / window_align) * window_align; - win->len = p->pack_size - win->offset; - if (win->len > packed_git_window_size) - win->len = packed_git_window_size; + len = p->pack_size - win->offset; + if (len > packed_git_window_size) + len = packed_git_window_size; + win->len = (size_t)len; pack_mapped += win->len; while (packed_git_limit < pack_mapped && unuse_one_window(p)) @@ -695,7 +706,7 @@ unsigned char* use_pack(struct packed_git *p, } offset -= win->offset; if (left) - *left = win->len - offset; + *left = win->len - xsize_t(offset); return win->base + offset; } @@ -871,9 +882,9 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size) */ sha1_file_open_flag = 0; } - map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + *size = xsize_t(st.st_size); + map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); - *size = st.st_size; return map; } @@ -1053,14 +1064,14 @@ static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type return unpack_sha1_rest(&stream, hdr, *size, sha1); } -static unsigned long get_delta_base(struct packed_git *p, +static off_t get_delta_base(struct packed_git *p, struct pack_window **w_curs, - unsigned long *curpos, + off_t *curpos, enum object_type type, - unsigned long delta_obj_offset) + off_t delta_obj_offset) { unsigned char *base_info = use_pack(p, w_curs, *curpos, NULL); - unsigned long base_offset; + off_t base_offset; /* use_pack() assured us we have [base_info, base_info + 20) * as a range that we can look at without walking off the @@ -1096,17 +1107,17 @@ static unsigned long get_delta_base(struct packed_git *p, } /* forward declaration for a mutually recursive function */ -static int packed_object_info(struct packed_git *p, unsigned long offset, +static int packed_object_info(struct packed_git *p, off_t offset, unsigned long *sizep); static int packed_delta_info(struct packed_git *p, struct pack_window **w_curs, - unsigned long curpos, + off_t curpos, enum object_type type, - unsigned long obj_offset, + off_t obj_offset, unsigned long *sizep) { - unsigned long base_offset; + off_t base_offset; base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset); type = packed_object_info(p, base_offset, NULL); @@ -1156,7 +1167,7 @@ static int packed_delta_info(struct packed_git *p, static int unpack_object_header(struct packed_git *p, struct pack_window **w_curs, - unsigned long *curpos, + off_t *curpos, unsigned long *sizep) { unsigned char *base; @@ -1180,14 +1191,15 @@ static int unpack_object_header(struct packed_git *p, } const char *packed_object_info_detail(struct packed_git *p, - unsigned long obj_offset, + off_t obj_offset, unsigned long *size, unsigned long *store_size, unsigned int *delta_chain_length, unsigned char *base_sha1) { struct pack_window *w_curs = NULL; - unsigned long curpos, dummy; + off_t curpos; + unsigned long dummy; unsigned char *next_sha1; enum object_type type; @@ -1211,6 +1223,7 @@ const char *packed_object_info_detail(struct packed_git *p, obj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset); if (*delta_chain_length == 0) { /* TODO: find base_sha1 as pointed by curpos */ + hashclr(base_sha1); } break; case OBJ_REF_DELTA: @@ -1226,11 +1239,12 @@ const char *packed_object_info_detail(struct packed_git *p, } } -static int packed_object_info(struct packed_git *p, unsigned long obj_offset, +static int packed_object_info(struct packed_git *p, off_t obj_offset, unsigned long *sizep) { struct pack_window *w_curs = NULL; - unsigned long size, curpos = obj_offset; + unsigned long size; + off_t curpos = obj_offset; enum object_type type; type = unpack_object_header(p, &w_curs, &curpos, &size); @@ -1258,7 +1272,7 @@ static int packed_object_info(struct packed_git *p, unsigned long obj_offset, static void *unpack_compressed_entry(struct packed_git *p, struct pack_window **w_curs, - unsigned long curpos, + off_t curpos, unsigned long size) { int st; @@ -1289,20 +1303,22 @@ static void *unpack_compressed_entry(struct packed_git *p, static void *unpack_delta_entry(struct packed_git *p, struct pack_window **w_curs, - unsigned long curpos, + off_t curpos, unsigned long delta_size, - unsigned long obj_offset, + off_t obj_offset, enum object_type *type, unsigned long *sizep) { void *delta_data, *result, *base; - unsigned long base_size, base_offset; + unsigned long base_size; + off_t base_offset; base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset); base = unpack_entry(p, base_offset, type, &base_size); if (!base) - die("failed to read delta base object at %lu from %s", - base_offset, p->pack_name); + die("failed to read delta base object" + " at %"PRIuMAX" from %s", + (uintmax_t)base_offset, p->pack_name); delta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size); result = patch_delta(base, base_size, @@ -1315,11 +1331,11 @@ static void *unpack_delta_entry(struct packed_git *p, return result; } -void *unpack_entry(struct packed_git *p, unsigned long obj_offset, +void *unpack_entry(struct packed_git *p, off_t obj_offset, enum object_type *type, unsigned long *sizep) { struct pack_window *w_curs = NULL; - unsigned long curpos = obj_offset; + off_t curpos = obj_offset; void *data; *type = unpack_object_header(p, &w_curs, &curpos, sizep); @@ -1342,23 +1358,23 @@ void *unpack_entry(struct packed_git *p, unsigned long obj_offset, return data; } -int num_packed_objects(const struct packed_git *p) +uint32_t num_packed_objects(const struct packed_git *p) { /* See check_packed_git_idx() */ - return (p->index_size - 20 - 20 - 4*256) / 24; + return (uint32_t)((p->index_size - 20 - 20 - 4*256) / 24); } -int nth_packed_object_sha1(const struct packed_git *p, int n, +int nth_packed_object_sha1(const struct packed_git *p, uint32_t n, unsigned char* sha1) { void *index = p->index_base + 256; - if (n < 0 || num_packed_objects(p) <= n) + if (num_packed_objects(p) <= n) return -1; hashcpy(sha1, (unsigned char *) index + (24 * n) + 4); return 0; } -unsigned long find_pack_entry_one(const unsigned char *sha1, +off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *p) { uint32_t *level1_ofs = p->index_base; @@ -1400,7 +1416,7 @@ static int matches_pack_name(struct packed_git *p, const char *ig) static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed) { struct packed_git *p; - unsigned long offset; + off_t offset; prepare_packed_git(); @@ -2067,11 +2083,10 @@ int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object) int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path) { - unsigned long size = st->st_size; - void *buf; + size_t size = xsize_t(st->st_size); + void *buf = NULL; int ret, re_allocated = 0; - buf = ""; if (size) buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); @@ -2111,6 +2126,7 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write { int fd; char *target; + size_t len; switch (st->st_mode & S_IFMT) { case S_IFREG: @@ -2123,16 +2139,17 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write path); break; case S_IFLNK: - target = xmalloc(st->st_size+1); - if (readlink(path, target, st->st_size+1) != st->st_size) { + len = xsize_t(st->st_size); + target = xmalloc(len + 1); + if (readlink(path, target, len + 1) != st->st_size) { char *errstr = strerror(errno); free(target); return error("readlink(\"%s\"): %s", path, errstr); } if (!write_object) - hash_sha1_file(target, st->st_size, blob_type, sha1); - else if (write_sha1_file(target, st->st_size, blob_type, sha1)) + hash_sha1_file(target, len, blob_type, sha1); + else if (write_sha1_file(target, len, blob_type, sha1)) return error("%s: failed to insert into database", path); free(target); diff --git a/sha1_name.c b/sha1_name.c index 0781477a71..31812d3d26 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -76,10 +76,10 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne prepare_packed_git(); for (p = packed_git; p && found < 2; p = p->next) { - unsigned num = num_packed_objects(p); - unsigned first = 0, last = num; + uint32_t num = num_packed_objects(p); + uint32_t first = 0, last = num; while (first < last) { - unsigned mid = (first + last) / 2; + uint32_t mid = (first + last) / 2; unsigned char now[20]; int cmp; diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 87403da780..cacb273aff 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -114,7 +114,8 @@ test_expect_success \ test_expect_success \ 'some edit' \ 'mv file file.orig && - sed -e "s/^3A/99/" -e "/^1A/d" < file.orig > file && + sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" < file.orig > file && + echo "incomplete" | tr -d "\\012" >>file && GIT_AUTHOR_NAME="D" git commit -a -m "edit"' test_expect_success \ diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 49b5666b33..ee386cfbf3 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -391,6 +391,22 @@ EOF test_expect_success "rename succeeded" "diff -u expect .git/config" +cat >> .git/config << EOF + [branch "zwei"] a = 1 [branch "vier"] +EOF + +test_expect_success "remove section" "git config --remove-section branch.zwei" + +cat > expect << EOF +# Hallo + #Bello +[branch "drei"] +weird +EOF + +test_expect_success "section was removed properly" \ + "diff -u expect .git/config" + test_expect_success numbers ' git-config kilo.gram 1k && diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 7d93d0d7c9..b1c97b0dfb 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -108,9 +108,9 @@ test_expect_success \ cd victim && git-config receive.denyNonFastforwards true && cd .. && - git-update-ref refs/heads/master master^ && - git-send-pack --force ./victim/.git/ master && - ! diff -u .git/refs/heads/master victim/.git/refs/heads/master + git-update-ref refs/heads/master master^ || return 1 + git-send-pack --force ./victim/.git/ master && return 1 + ! diff .git/refs/heads/master victim/.git/refs/heads/master ' test_done diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 0514056ca6..0c0034e34c 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -11,47 +11,91 @@ test_expect_success setup ' git-update-index --add a && tree0=$(git-write-tree) && commit0=$(echo setup | git-commit-tree $tree0) && - git-update-ref HEAD $commit0 && - git-clone ./. victim && echo We hope it works. >a && git-update-index a && tree1=$(git-write-tree) && commit1=$(echo modify | git-commit-tree $tree1 -p $commit0) && - git-update-ref HEAD $commit1 + git-update-ref refs/heads/master $commit0 && + git-update-ref refs/heads/tofail $commit1 && + git-clone ./. victim && + GIT_DIR=victim/.git git-update-ref refs/heads/tofail $commit1 && + git-update-ref refs/heads/master $commit1 && + git-update-ref refs/heads/tofail $commit0 ' +cat >victim/.git/hooks/pre-receive <<'EOF' +#!/bin/sh +echo "$@" >>$GIT_DIR/pre-receive.args +read x; printf "$x" >$GIT_DIR/pre-receive.stdin +echo STDOUT pre-receive +echo STDERR pre-receive >&2 +EOF +chmod u+x victim/.git/hooks/pre-receive + cat >victim/.git/hooks/update <<'EOF' #!/bin/sh -echo "$@" >$GIT_DIR/update.args +echo "$@" >>$GIT_DIR/update.args read x; printf "$x" >$GIT_DIR/update.stdin -echo STDOUT update -echo STDERR update >&2 +echo STDOUT update $1 +echo STDERR update $1 >&2 +test "$1" = refs/heads/master || exit EOF chmod u+x victim/.git/hooks/update +cat >victim/.git/hooks/post-receive <<'EOF' +#!/bin/sh +echo "$@" >>$GIT_DIR/post-receive.args +read x; printf "$x" >$GIT_DIR/post-receive.stdin +echo STDOUT post-receive +echo STDERR post-receive >&2 +EOF +chmod u+x victim/.git/hooks/post-receive + cat >victim/.git/hooks/post-update <<'EOF' #!/bin/sh -echo "$@" >$GIT_DIR/post-update.args +echo "$@" >>$GIT_DIR/post-update.args read x; printf "$x" >$GIT_DIR/post-update.stdin echo STDOUT post-update echo STDERR post-update >&2 EOF chmod u+x victim/.git/hooks/post-update -test_expect_success push ' - git-send-pack ./victim/.git/ master >send.out 2>send.err +test_expect_failure push ' + git-send-pack --force ./victim/.git master tofail >send.out 2>send.err +' + +test_expect_success 'updated as expected' ' + test $(GIT_DIR=victim/.git git-rev-parse master) = $commit1 && + test $(GIT_DIR=victim/.git git-rev-parse tofail) = $commit1 ' test_expect_success 'hooks ran' ' + test -f victim/.git/pre-receive.args && + test -f victim/.git/pre-receive.stdin && test -f victim/.git/update.args && test -f victim/.git/update.stdin && + test -f victim/.git/post-receive.args && + test -f victim/.git/post-receive.stdin && test -f victim/.git/post-update.args && test -f victim/.git/post-update.stdin ' +test_expect_success 'pre-receive hook arguments' ' + echo \ + refs/heads/master $commit0 $commit1 \ + refs/heads/tofail $commit1 $commit0 \ + | diff - victim/.git/pre-receive.args +' + test_expect_success 'update hook arguments' ' + (echo refs/heads/master $commit0 $commit1; + echo refs/heads/tofail $commit1 $commit0 + ) | diff - victim/.git/update.args +' + +test_expect_success 'post-receive hook arguments' ' echo refs/heads/master $commit0 $commit1 | - diff -u - victim/.git/update.args + diff - victim/.git/post-receive.args ' test_expect_success 'post-update hook arguments' ' @@ -59,23 +103,32 @@ test_expect_success 'post-update hook arguments' ' diff -u - victim/.git/post-update.args ' -test_expect_failure 'update hook stdin is /dev/null' ' - test -s victim/.git/update.stdin -' - -test_expect_failure 'post-update hook stdin is /dev/null' ' - test -s victim/.git/post-update.stdin +test_expect_success 'all hook stdin is /dev/null' ' + ! test -s victim/.git/pre-receive.stdin && + ! test -s victim/.git/update.stdin && + ! test -s victim/.git/post-receive.stdin && + ! test -s victim/.git/post-update.stdin ' test_expect_failure 'send-pack produced no output' ' test -s send.out ' +cat <<EOF >expect +STDOUT pre-receive +STDERR pre-receive +STDOUT update refs/heads/master +STDERR update refs/heads/master +STDOUT update refs/heads/tofail +STDERR update refs/heads/tofail +STDOUT post-receive +STDERR post-receive +STDOUT post-update +STDERR post-update +EOF test_expect_success 'send-pack stderr contains hook messages' ' - grep "STDOUT update" send.err && - grep "STDERR update" send.err && - grep "STDOUT post-update" send.err && - grep "STDERR post-update" send.err + egrep ^STD send.err >actual && + diff - actual <expect ' test_done diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 765c83fda7..0b600bb429 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -114,6 +114,7 @@ done >> tests # neither in the Pull: or .fetch config for branch in master br-unconfig ; do cat <<EOF +$branch ../.git $branch ../.git one $branch ../.git one two $branch --tags ../.git diff --git a/t/t5515/fetch.br-unconfig_.._.git b/t/t5515/fetch.br-unconfig_.._.git new file mode 100644 index 0000000000..284bb1fb61 --- /dev/null +++ b/t/t5515/fetch.br-unconfig_.._.git @@ -0,0 +1,2 @@ +# br-unconfig ../.git +0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../ diff --git a/t/t5515/fetch.master_.._.git b/t/t5515/fetch.master_.._.git new file mode 100644 index 0000000000..66d1aaddae --- /dev/null +++ b/t/t5515/fetch.master_.._.git @@ -0,0 +1,2 @@ +# master ../.git +0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../ diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 970d683650..2e1a09ff2d 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -111,6 +111,14 @@ test_expect_success \ 'A: verify marks output' \ 'diff -u expect marks.out' +test_expect_success \ + 'A: verify marks import' \ + 'git-fast-import \ + --import-marks=marks.out \ + --export-marks=marks.new \ + </dev/null && + diff -u expect marks.new' + ### ### series B ### diff --git a/templates/Makefile b/templates/Makefile index 0eeee43feb..b8352e731b 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -1,5 +1,9 @@ # make and install sample templates +ifndef V + QUIET = @ +endif + INSTALL ?= install TAR ?= tar prefix ?= $(HOME) @@ -18,7 +22,7 @@ all: boilerplates.made custom bpsrc = $(filter-out %~,$(wildcard *--*)) boilerplates.made : $(bpsrc) - ls *--* 2>/dev/null | \ + $(QUIET)ls *--* 2>/dev/null | \ while read boilerplate; \ do \ case "$$boilerplate" in *~) continue ;; esac && \ @@ -29,13 +33,13 @@ boilerplates.made : $(bpsrc) *--) ;; \ *) cp $$boilerplate blt/$$dst ;; \ esac || exit; \ - done || exit + done && \ date >$@ # If you need build-tailored templates, build them into blt/ # directory yourself here. custom: - : no custom templates yet + $(QUIET): no custom templates yet clean: rm -rf blt boilerplates.made diff --git a/xdiff-interface.c b/xdiff-interface.c index 6c1f99b149..10816e95a0 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -107,16 +107,18 @@ int read_mmfile(mmfile_t *ptr, const char *filename) { struct stat st; FILE *f; + size_t sz; if (stat(filename, &st)) return error("Could not stat %s", filename); if ((f = fopen(filename, "rb")) == NULL) return error("Could not open %s", filename); - ptr->ptr = xmalloc(st.st_size); - if (fread(ptr->ptr, st.st_size, 1, f) != 1) + sz = xsize_t(st.st_size); + ptr->ptr = xmalloc(sz); + if (fread(ptr->ptr, sz, 1, f) != 1) return error("Could not read %s", filename); fclose(f); - ptr->size = st.st_size; + ptr->size = sz; return 0; } |