Code

git.git
13 years agodiff: refactor COLOR_DIFF from a flag into an int
Jeff King [Thu, 18 Aug 2011 05:03:12 +0000 (22:03 -0700)]
diff: refactor COLOR_DIFF from a flag into an int

This lets us store more than just a bit flag for whether we
want color; we can also store whether we want automatic
colors. This can be useful for making the automatic-color
decision closer to the point of use.

This mostly just involves replacing DIFF_OPT_* calls with
manipulations of the flag. The biggest exception is that
calls to DIFF_OPT_TST must check for "o->use_color > 0",
which lets an "unknown" value (i.e., the default) stay at
"no color". In the previous code, a value of "-1" was not
propagated at all.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agosetup_pager: set GIT_PAGER_IN_USE
Jeff King [Thu, 18 Aug 2011 05:02:29 +0000 (22:02 -0700)]
setup_pager: set GIT_PAGER_IN_USE

We have always set a global "spawned_pager" variable when we
start the pager. This lets us make the auto-color decision
later in the program as as "we are outputting to a terminal,
or to a pager which can handle colors".

Commit 6e9af86 added support for the GIT_PAGER_IN_USE
environment variable. An external program calling git (e.g.,
git-svn) could set this variable to indicate that it had
already started the pager, and that the decision about
auto-coloring should take that into account.

However, 6e9af86 failed to do the reverse, which is to tell
external programs when git itself has started the pager.
Thus a git command implemented as an external script that
has the pager turned on (e.g., "git -p stash show") would
not realize it was going to a pager, and would suppress
colors.

This patch remedies that; we always set GIT_PAGER_IN_USE
when we start the pager, and the value is respected by both
this program and any spawned children.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot7006: use test_config helpers
Jeff King [Thu, 18 Aug 2011 05:02:06 +0000 (22:02 -0700)]
t7006: use test_config helpers

In some cases, this is just making the test script a little
shorter and easier to read. However, there are several
places where we didn't take proper precautions against
polluting downstream tests with our config; this fixes them,
too.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agotest-lib: add helper functions for config
Jeff King [Thu, 18 Aug 2011 05:01:15 +0000 (22:01 -0700)]
test-lib: add helper functions for config

There are a few common tasks when working with configuration
variables in tests; this patch aims to make them a little
easier to write and less error-prone.

When setting a variable, you should typically make sure to
clean it up after the test is finished, so as not to pollute
other tests. Like:

   test_when_finished 'git config --unset foo.bar' &&
   git config foo.bar baz

This patch lets you just write:

  test_config foo.bar baz

When clearing a variable that does not exist, git-config
will report a specific non-zero error code. Meaning that
tests which call "git config --unset" often either rely on
the prior tests having actually set it, or must use
test_might_fail. With this patch, the previous:

  test_might_fail git config --unset foo.bar

becomes:

  test_unconfig foo.bar

Not only is this easier to type, but it is more robust; it
will correctly detect errors from git-config besides "key
was not set".

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot7006: modernize calls to unset
Jeff King [Thu, 18 Aug 2011 05:00:47 +0000 (22:00 -0700)]
t7006: modernize calls to unset

These tests break &&-chaining to deal with broken "unset"
implementations. Instead, they should just use sane_unset.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agofetch-pack: check for valid commit from server
Nguyễn Thái Ngọc Duy [Thu, 18 Aug 2011 13:36:03 +0000 (20:36 +0700)]
fetch-pack: check for valid commit from server

A malicious server can return ACK with non-existent SHA-1 or not a
commit. lookup_commit() in this case may return NULL. Do not let
fetch-pack crash by accessing NULL address in this case.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agolog: decorate grafted commits with "grafted"
Nguyễn Thái Ngọc Duy [Thu, 18 Aug 2011 12:29:37 +0000 (19:29 +0700)]
log: decorate grafted commits with "grafted"

In shallow repositories, this may help detect whether a branch ends,
or it is deeper than current depth.

It also show graft points that extend a branch.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoMove write_shallow_commits to fetch-pack.c
Nguyễn Thái Ngọc Duy [Thu, 18 Aug 2011 12:29:36 +0000 (19:29 +0700)]
Move write_shallow_commits to fetch-pack.c

This function produces network traffic and should be in fetch-pack. It
has been in commit.c because it needs to iterate (private) graft
list. It can now do so using for_each_commit_graft().

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoAdd for_each_commit_graft() to iterate all grafts
Nguyễn Thái Ngọc Duy [Thu, 18 Aug 2011 12:29:35 +0000 (19:29 +0700)]
Add for_each_commit_graft() to iterate all grafts

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agodecoration: do not mis-decorate refs with same prefix
Nguyễn Thái Ngọc Duy [Thu, 18 Aug 2011 12:29:34 +0000 (19:29 +0700)]
decoration: do not mis-decorate refs with same prefix

We definitely do not want to decorate refs/headsandtails the same as
refs/heads/*, for example.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoUpdate draft release notes to 1.7.7
Junio C Hamano [Thu, 18 Aug 2011 00:48:36 +0000 (17:48 -0700)]
Update draft release notes to 1.7.7

Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoMerge branch 'mh/check-attr-relative'
Junio C Hamano [Thu, 18 Aug 2011 00:36:22 +0000 (17:36 -0700)]
Merge branch 'mh/check-attr-relative'

* mh/check-attr-relative: (29 commits)
  test-path-utils: Add subcommand "prefix_path"
  test-path-utils: Add subcommand "absolute_path"
  git-check-attr: Normalize paths
  git-check-attr: Demonstrate problems with relative paths
  git-check-attr: Demonstrate problems with unnormalized paths
  git-check-attr: test that no output is written to stderr
  Rename git_checkattr() to git_check_attr()
  git-check-attr: Fix command-line handling to match docs
  git-check-attr: Drive two tests using the same raw data
  git-check-attr: Add an --all option to show all attributes
  git-check-attr: Error out if no pathnames are specified
  git-check-attr: Process command-line args more systematically
  git-check-attr: Handle each error separately
  git-check-attr: Extract a function error_with_usage()
  git-check-attr: Introduce a new variable
  git-check-attr: Extract a function output_attr()
  Allow querying all attributes on a file
  Remove redundant check
  Remove redundant call to bootstrap_attr_stack()
  Extract a function collect_all_attrs()
  ...

13 years agoMerge branch 'js/bisect-no-checkout'
Junio C Hamano [Thu, 18 Aug 2011 00:36:09 +0000 (17:36 -0700)]
Merge branch 'js/bisect-no-checkout'

* js/bisect-no-checkout:
  bisect: add support for bisecting bare repositories
  bisect: further style nitpicks
  bisect: replace "; then" with "\n<tab>*then"
  bisect: cleanup whitespace errors in git-bisect.sh.
  bisect: add documentation for --no-checkout option.
  bisect: add tests for the --no-checkout option.
  bisect: introduce --no-checkout support into porcelain.
  bisect: introduce support for --no-checkout option.
  bisect: add tests to document expected behaviour in presence of broken trees.
  bisect: use && to connect statements that are deferred with eval.
  bisect: move argument parsing before state modification.

13 years agoMerge branch 'rc/histogram-diff'
Junio C Hamano [Thu, 18 Aug 2011 00:36:06 +0000 (17:36 -0700)]
Merge branch 'rc/histogram-diff'

* rc/histogram-diff:
  xdiff/xhistogram: drop need for additional variable
  xdiff/xhistogram: rely on xdl_trim_ends()
  xdiff/xhistogram: rework handling of recursed results
  xdiff: do away with xdl_mmfile_next()
  Make test number unique
  xdiff/xprepare: use a smaller sample size for histogram diff
  xdiff/xprepare: skip classification
  teach --histogram to diff
  t4033-diff-patience: factor out tests
  xdiff/xpatience: factor out fall-back-diff function
  xdiff/xprepare: refactor abort cleanups
  xdiff/xprepare: use memset()

13 years agoMerge branch 'jc/maint-smart-http-race-upload-pack'
Junio C Hamano [Thu, 18 Aug 2011 00:35:58 +0000 (17:35 -0700)]
Merge branch 'jc/maint-smart-http-race-upload-pack'

* jc/maint-smart-http-race-upload-pack:
  helping smart-http/stateless-rpc fetch race

13 years agoMerge branch 'js/sh-style'
Junio C Hamano [Thu, 18 Aug 2011 00:35:50 +0000 (17:35 -0700)]
Merge branch 'js/sh-style'

* js/sh-style:
  filter-branch.sh: de-dent usage string
  misc-sh: fix up whitespace in some other .sh files.

13 years agoMerge branch 'js/ref-namespaces'
Junio C Hamano [Thu, 18 Aug 2011 00:35:38 +0000 (17:35 -0700)]
Merge branch 'js/ref-namespaces'

* js/ref-namespaces:
  ref namespaces: tests
  ref namespaces: documentation
  ref namespaces: Support remote repositories via upload-pack and receive-pack
  ref namespaces: infrastructure
  Fix prefix handling in ref iteration functions

13 years agoMerge branch 'cb/maint-quiet-push'
Junio C Hamano [Thu, 18 Aug 2011 00:26:05 +0000 (17:26 -0700)]
Merge branch 'cb/maint-quiet-push'

* cb/maint-quiet-push:
  receive-pack: do not overstep command line argument array
  propagate --quiet to send-pack/receive-pack

Conflicts:
Documentation/git-receive-pack.txt
Documentation/git-send-pack.txt

13 years agoMerge branch 'jc/maint-combined-diff-work-tree'
Junio C Hamano [Thu, 18 Aug 2011 00:25:59 +0000 (17:25 -0700)]
Merge branch 'jc/maint-combined-diff-work-tree'

* jc/maint-combined-diff-work-tree:
  diff -c/--cc: do not mistake "resolved as deletion" as "use working tree"

Conflicts:
combine-diff.c

13 years agoMerge branch 'cb/maint-exec-error-report'
Junio C Hamano [Thu, 18 Aug 2011 00:25:55 +0000 (17:25 -0700)]
Merge branch 'cb/maint-exec-error-report'

* cb/maint-exec-error-report:
  notice error exit from pager
  error_routine: use parent's stderr if exec fails

13 years agoMerge branch 'maint'
Junio C Hamano [Thu, 18 Aug 2011 00:25:37 +0000 (17:25 -0700)]
Merge branch 'maint'

* maint:
  checkout-index: remove obsolete comment

13 years agodoc/fast-import: document feature import-marks-if-exists
Dmitry Ivankov [Wed, 17 Aug 2011 10:42:58 +0000 (16:42 +0600)]
doc/fast-import: document feature import-marks-if-exists

fast-import command-line option --import-marks-if-exists was introduced
in commit dded4f1 (fast-import: Introduce --import-marks-if-exists, 2011-01-15)

--import-marks option can be set via a "feature" command in a fast-import
stream and --import-marks-if-exists had support for such specification
from the very beginning too due to some shared codebase. Though the
documentation for this feature wasn't written in dded4f1.

Add the documentation for "feature import-marks-if-exists=<file>". Also add
a minimalistic test for it.

Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agocheckout-index: remove obsolete comment
Nguyễn Thái Ngọc Duy [Wed, 17 Aug 2011 12:22:13 +0000 (19:22 +0700)]
checkout-index: remove obsolete comment

The first paragraph about flag order is no longer true and is
mentioned in git-checkout-index.txt. The rest is also mentioned in
git-checkout-index.txt.

Remove it and keep uptodate document in one place.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoSync with "maint"
Junio C Hamano [Tue, 16 Aug 2011 21:23:43 +0000 (14:23 -0700)]
Sync with "maint"

Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoMerge branch 'maint'
Junio C Hamano [Tue, 16 Aug 2011 21:22:26 +0000 (14:22 -0700)]
Merge branch 'maint'

* maint:
  Prepare for 1.7.6.1
  am: refresh the index at start and --resolved

Conflicts:
GIT-VERSION-GEN
RelNotes

13 years agomerge-recursive: take advantage of hardcoded empty tree
Jonathan Nieder [Tue, 16 Aug 2011 18:27:39 +0000 (13:27 -0500)]
merge-recursive: take advantage of hardcoded empty tree

When this code was first written (v1.4.3-rc1~174^2~4, merge-recur: if
there is no common ancestor, fake empty one, 2006-08-09), everyone
needing a fake empty tree had to make her own, but ever since
v1.5.5-rc0~180^2~1 (2008-02-13), the object lookup machinery provides
a ready-made one.  Use it.

This is just a simplification, though it also fixes a small leak
(since the tree in the virtual common ancestor commit is never freed).

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoPrepare for 1.7.6.1
Junio C Hamano [Tue, 16 Aug 2011 19:13:38 +0000 (12:13 -0700)]
Prepare for 1.7.6.1

Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoMerge branch 'jk/tag-list-multiple-patterns' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:14 +0000 (12:41 -0700)]
Merge branch 'jk/tag-list-multiple-patterns' into maint

* jk/tag-list-multiple-patterns:
  tag: accept multiple patterns for --list

13 years agoMerge branch 'jl/submodule-update-quiet' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:14 +0000 (12:41 -0700)]
Merge branch 'jl/submodule-update-quiet' into maint

* jl/submodule-update-quiet:
  submodule: update and add must honor --quiet flag

13 years agoMerge branch 'jl/submodule-add-relurl-wo-upstream' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:13 +0000 (12:41 -0700)]
Merge branch 'jl/submodule-add-relurl-wo-upstream' into maint

* jl/submodule-add-relurl-wo-upstream:
  submodule add: clean up duplicated code
  submodule add: allow relative repository path even when no url is set
  submodule add: test failure when url is not configured in superproject

Conflicts:
git-submodule.sh

13 years agoMerge branch 'oa/pull-reflog' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:13 +0000 (12:41 -0700)]
Merge branch 'oa/pull-reflog' into maint

* oa/pull-reflog:
  pull: remove extra space from reflog message

13 years agoMerge branch 'js/ls-tree-error' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:12 +0000 (12:41 -0700)]
Merge branch 'js/ls-tree-error' into maint

* js/ls-tree-error:
  Ensure git ls-tree exits with a non-zero exit code if read_tree_recursive fails.
  Add a test to check that git ls-tree sets non-zero exit code on error.

13 years agoMerge branch 'jk/fast-export-quote-path' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:12 +0000 (12:41 -0700)]
Merge branch 'jk/fast-export-quote-path' into maint

* jk/fast-export-quote-path:
  fast-export: quote paths in output

13 years agoMerge branch 'jc/checkout-reflog-fix' into maint
Junio C Hamano [Tue, 16 Aug 2011 19:41:12 +0000 (12:41 -0700)]
Merge branch 'jc/checkout-reflog-fix' into maint

* jc/checkout-reflog-fix:
  checkout: do not write bogus reflog entry out

13 years agoMerge branch 'jc/maint-reset-unmerged-path' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:28 +0000 (11:41 -0700)]
Merge branch 'jc/maint-reset-unmerged-path' into maint

* jc/maint-reset-unmerged-path:
  reset [<commit>] paths...: do not mishandle unmerged paths

13 years agoMerge branch 'mz/doc-rebase-abort' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:28 +0000 (11:41 -0700)]
Merge branch 'mz/doc-rebase-abort' into maint

* mz/doc-rebase-abort:
  rebase: clarify "restore the original branch"

13 years agoMerge branch 'bw/log-all-ref-updates-doc' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:28 +0000 (11:41 -0700)]
Merge branch 'bw/log-all-ref-updates-doc' into maint

* bw/log-all-ref-updates-doc:
  Documentation: clearly specify what refs are honored by core.logAllRefUpdates

13 years agoMerge branch 'js/maint-add-path-stat-pwd' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:27 +0000 (11:41 -0700)]
Merge branch 'js/maint-add-path-stat-pwd' into maint

* js/maint-add-path-stat-pwd:
  get_pwd_cwd(): Do not trust st_dev/st_ino blindly

13 years agoMerge branch 'ms/help-unknown' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:27 +0000 (11:41 -0700)]
Merge branch 'ms/help-unknown' into maint

* ms/help-unknown:
  help_unknown_cmd: do not propose an "unknown" cmd

13 years agoMerge branch 'mz/doc-synopsis-verse' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:26 +0000 (11:41 -0700)]
Merge branch 'mz/doc-synopsis-verse' into maint

* mz/doc-synopsis-verse:
  Documentation: use [verse] for SYNOPSIS sections

13 years agoMerge branch 'jn/mime-type-with-params' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:26 +0000 (11:41 -0700)]
Merge branch 'jn/mime-type-with-params' into maint

* jn/mime-type-with-params:
  gitweb: Serve */*+xml 'blob_plain' as text/plain with $prevent_xss
  gitweb: Serve text/* 'blob_plain' as text/plain with $prevent_xss

13 years agoMerge branch 'jc/submodule-sync-no-auto-vivify' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:41:26 +0000 (11:41 -0700)]
Merge branch 'jc/submodule-sync-no-auto-vivify' into maint

* jc/submodule-sync-no-auto-vivify:
  submodule add: always initialize .git/config entry
  submodule sync: do not auto-vivify uninteresting submodule

13 years agoMerge branch 'jc/zlib-wrap' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)]
Merge branch 'jc/zlib-wrap' into maint

* jc/zlib-wrap:
  zlib: allow feeding more than 4GB in one go
  zlib: zlib can only process 4GB at a time
  zlib: wrap deflateBound() too
  zlib: wrap deflate side of the API
  zlib: wrap inflateInit2 used to accept only for gzip format
  zlib: wrap remaining calls to direct inflate/inflateEnd
  zlib wrapper: refactor error message formatter

13 years agoMerge branch 'fk/relink-upon-ldflags-update' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)]
Merge branch 'fk/relink-upon-ldflags-update' into maint

* fk/relink-upon-ldflags-update:
  Makefile: Track changes to LDFLAGS and relink when necessary

13 years agoMerge branch 'bc/submodule-foreach-stdin-fix-1.7.4' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)]
Merge branch 'bc/submodule-foreach-stdin-fix-1.7.4' into maint

* bc/submodule-foreach-stdin-fix-1.7.4:
  git-submodule.sh: preserve stdin for the command spawned by foreach
  t/t7407: demonstrate that the command called by 'submodule foreach' loses stdin

13 years agoMerge branch 'aw/rebase-i-p' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:25 +0000 (11:23 -0700)]
Merge branch 'aw/rebase-i-p' into maint

* aw/rebase-i-p:
  rebase -i -p: include non-first-parent commits in todo list

13 years agoMerge branch 'jc/diff-index-quick-exit-early' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:25 +0000 (11:23 -0700)]
Merge branch 'jc/diff-index-quick-exit-early' into maint

* jc/diff-index-quick-exit-early:
  diff-index --quiet: learn the "stop feeding the backend early" logic

Conflicts:
unpack-trees.h

13 years agoMerge branch 'jk/combine-diff-binary-etc' into maint
Junio C Hamano [Tue, 16 Aug 2011 18:23:24 +0000 (11:23 -0700)]
Merge branch 'jk/combine-diff-binary-etc' into maint

* jk/combine-diff-binary-etc:
  combine-diff: respect textconv attributes
  refactor get_textconv to not require diff_filespec
  combine-diff: handle binary files as binary
  combine-diff: calculate mode_differs earlier
  combine-diff: split header printing into its own function

13 years agoam: refresh the index at start and --resolved
Jeff King [Tue, 16 Aug 2011 00:13:07 +0000 (17:13 -0700)]
am: refresh the index at start and --resolved

If a file is unchanged but stat-dirty, we may erroneously
fail to apply patches, thinking that they conflict with a
dirty working tree.

This patch adds a call to "update-index --refresh". It comes
as late as possible, so that we don't bother with it for
thinks like "git rebase --abort", or when mbox-splitting
fails. However, it does come before we actually start
applying patches, meaning we will only call it once when we
start applying patches (or any time we return to "am" after
having resolved conflicts), and not once per patch.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agorevert: plug memory leak in "cherry-pick root commit" codepath
Jonathan Nieder [Sun, 14 Aug 2011 15:22:04 +0000 (10:22 -0500)]
revert: plug memory leak in "cherry-pick root commit" codepath

The empty tree passed as common ancestor to merge_trees() when
cherry-picking a parentless commit is allocated on the heap and never
freed.  Leaking such a small one-time allocation is not a very big
problem, but now that "git cherry-pick" can cherry-pick multiple
commits it can start to add up.

Avoid the leak by storing the fake tree exactly once in the BSS
section (i.e., use a static).  While at it, let's add a test to make
sure cherry-picking multiple parentless commits continues to work.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoUnroll the loop over passes
Michael Haggerty [Fri, 12 Aug 2011 21:43:10 +0000 (23:43 +0200)]
Unroll the loop over passes

The passes no longer share much code, and the unrolled code is easier
to understand.

Use a new index variable instead of num_attr for the second loop, as
we are no longer counting attributes but rather indexing through them.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoChange while loop into for loop
Michael Haggerty [Fri, 12 Aug 2011 21:43:09 +0000 (23:43 +0200)]
Change while loop into for loop

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoDetermine the start of the states outside of the pass loop
Michael Haggerty [Fri, 12 Aug 2011 21:43:08 +0000 (23:43 +0200)]
Determine the start of the states outside of the pass loop

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoChange parse_attr() to take a pointer to struct attr_state
Michael Haggerty [Fri, 12 Aug 2011 21:43:07 +0000 (23:43 +0200)]
Change parse_attr() to take a pointer to struct attr_state

parse_attr() only needs access to the attr_state to which it should
store its results, not to the whole match_attr structure.  This change
also removes the need for it to know num_attr.  Change its signature
accordingly and add a comment.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoIncrement num_attr in parse_attr_line(), not parse_attr()
Michael Haggerty [Fri, 12 Aug 2011 21:43:06 +0000 (23:43 +0200)]
Increment num_attr in parse_attr_line(), not parse_attr()

num_attr is incremented iff parse_attr() returns non-NULL.  So do the
counting in parse_attr_line() instead of within parse_attr().  This
allows an integer rather than a pointer to an integer to be passed to
parse_attr().

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoDocument struct match_attr
Michael Haggerty [Fri, 12 Aug 2011 21:43:05 +0000 (23:43 +0200)]
Document struct match_attr

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agoAdd a file comment
Michael Haggerty [Fri, 12 Aug 2011 21:43:04 +0000 (23:43 +0200)]
Add a file comment

Consolidate here a few general comments plus links to other
documentation.  Delete a comment with an out-of-date description of
the .gitattributes file format.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agofast-import: prevent producing bad delta
Dmitry Ivankov [Sun, 14 Aug 2011 18:32:24 +0000 (00:32 +0600)]
fast-import: prevent producing bad delta

To produce deltas for tree objects fast-import tracks two versions
of tree's entries - base and current one. Base version stands both
for a delta base of this tree, and for a entry inside a delta base
of a parent tree. So care should be taken to keep it in sync.

tree_content_set cuts away a whole subtree and replaces it with a
new one (or NULL for lazy load of a tree with known sha1). It
keeps a base sha1 for this subtree (needed for parent tree). And
here is the problem, 'subtree' tree root doesn't have the implied
base version entries.

Adjusting the subtree to include them would mean a deep rewrite of
subtree. Invalidating the subtree base version would mean recursive
invalidation of parents' base versions. So just mark this tree as
do-not-delta me. Abuse setuid bit for this purpose.

tree_content_replace is the same as tree_content_set except that is
is used to replace the root, so just clearing base sha1 here (instead
of setting the bit) is fine.

[di: log message]

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agofast-import: add a test for tree delta base corruption
Dmitry Ivankov [Sun, 14 Aug 2011 18:32:23 +0000 (00:32 +0600)]
fast-import: add a test for tree delta base corruption

fast-import is able to write imported tree objects in delta format.
It holds a tree structure in memory where each tree entry may have
a delta base sha1 assigned. When delta base data is needed it is
reconstructed from this in-memory structure. Though sometimes the
delta base data doesn't match the delta base sha1 so wrong or even
corrupt pack is produced.

Add a small test that produces a corrupt pack. It uses just tree
copy and file modification commands aside from the very basic commit
and blob commands.

Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Don't re-sort a list whose order we depend upon
Elijah Newren [Sat, 13 Aug 2011 02:23:51 +0000 (20:23 -0600)]
merge-recursive: Don't re-sort a list whose order we depend upon

In record_df_conflict_files() we would resort the entries list using
df_name_compare to get a convenient ordering.  Unfortunately, this broke
assumptions of the get_renames() code (via string_list_lookup() calls)
which needed the list to be in the standard ordering.  When those lookups
would fail, duplicate stage_data entries could be inserted, causing the
process_renames and process_entry code to fail (in particular, a path that
that process_renames had marked as processed would still be processed
anyway in process_entry due to the duplicate entry).

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix virtual merge base for rename/rename(1to2)/add-dest
Elijah Newren [Fri, 12 Aug 2011 05:20:29 +0000 (23:20 -0600)]
merge-recursive: Fix virtual merge base for rename/rename(1to2)/add-dest

Earlier in this series, the patch "merge-recursive: add handling for
rename/rename/add-dest/add-dest" added code to handle the rename on each
side of history also being involved in a rename/add conflict, but only
did so in the non-recursive case.  Add code for the recursive case,
ensuring that the "added" files are not simply deleted.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot6036: criss-cross + rename/rename(1to2)/add-dest + simple modify
Elijah Newren [Fri, 12 Aug 2011 05:20:28 +0000 (23:20 -0600)]
t6036: criss-cross + rename/rename(1to2)/add-dest + simple modify

This is another testcase trying to exercise the virtual merge base
creation in the rename/rename(1to2) code.  A testcase is added that we
should be able to merge cleanly, but which requires a virtual merge base
to be created that correctly handles rename/add-dest conflicts within the
rename/rename(1to2) testcase handling.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Avoid unnecessary file rewrites
Elijah Newren [Fri, 12 Aug 2011 05:20:27 +0000 (23:20 -0600)]
merge-recursive: Avoid unnecessary file rewrites

Often times, a potential conflict at a path is resolved by merge-recursive
by using the content that was already present at that location.  In such
cases, we do not want to overwrite the content that is already present, as
that could trigger unnecessary recompilations.  One of the patches earlier
in this series ("merge-recursive: When we detect we can skip an update,
actually skip it") fixed the cases that involved content merges, but there
were a few other cases as well.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot6022: Additional tests checking for unnecessary updates of files
Elijah Newren [Fri, 12 Aug 2011 05:20:26 +0000 (23:20 -0600)]
t6022: Additional tests checking for unnecessary updates of files

I stumbled across a case, this one not involving a content merge, where
git currently rewrites a file unnecessarily.  A quick audit uncovered two
additional situations (also not involving content merges) with the same
problem.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix spurious 'refusing to lose untracked file...' messages
Elijah Newren [Fri, 12 Aug 2011 05:20:25 +0000 (23:20 -0600)]
merge-recursive: Fix spurious 'refusing to lose untracked file...' messages

Calling update_stages() before update_file() can sometimes result in git
thinking the file being updated is untracked (whenever update_stages
moves it to stage 3).  Reverse the call order, and add a big comment to
update_stages to hopefully prevent others from making the same mistake.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot6022: Add testcase for spurious "refusing to lose untracked" messages
Elijah Newren [Fri, 12 Aug 2011 05:20:24 +0000 (23:20 -0600)]
t6022: Add testcase for spurious "refusing to lose untracked" messages

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agot3030: fix accidental success in symlink rename
Jeff King [Fri, 12 Aug 2011 05:20:23 +0000 (23:20 -0600)]
t3030: fix accidental success in symlink rename

In this test, we have merge two branches. On one branch, we
renamed "a" to "e". On the other, we renamed "a" to "e" and
then added a symlink pointing at "a" pointing to "e".

The results for the test indicate that the merge should
succeed, but also that "a" should no longer exist. Since
both sides renamed "a" to the same destination, we will end
up comparing those destinations for content.

But what about what's left? One side (the rename only),
replaced "a" with nothing. The other side replaced it with a
symlink. The common base must also be nothing, because any
"a" before this was meaningless (it was totally unrelated
content that ended up getting renamed).

The only sensible resolution is to keep the symlink. The
rename-only side didn't touch the content versus the common
base, and the other side added content. The 3-way merge
dictates that we take the side with a change.

And this gives the overall merge an intuitive result.  One
side made one change (a rename), and the other side made two
changes: an identical rename, and an addition (that just
happened to be at the same spot). The end result should
contain both changes.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix working copy handling for rename/rename/add/add
Elijah Newren [Fri, 12 Aug 2011 05:20:22 +0000 (23:20 -0600)]
merge-recursive: Fix working copy handling for rename/rename/add/add

If either side of a rename/rename(1to2) conflict is itself also involved
in a rename/add-dest conflict, then we need to make sure both the rename
and the added file appear in the working copy.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: add handling for rename/rename/add-dest/add-dest
Elijah Newren [Fri, 12 Aug 2011 05:20:21 +0000 (23:20 -0600)]
merge-recursive: add handling for rename/rename/add-dest/add-dest

Each side of the rename in rename/rename(1to2) could potentially also be
involved in a rename/add conflict.  Ensure stages for such conflicts are
also recorded.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Have conflict_rename_delete reuse modify/delete code
Elijah Newren [Fri, 12 Aug 2011 05:20:20 +0000 (23:20 -0600)]
merge-recursive: Have conflict_rename_delete reuse modify/delete code

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Make modify/delete handling code reusable
Elijah Newren [Fri, 12 Aug 2011 05:20:19 +0000 (23:20 -0600)]
merge-recursive: Make modify/delete handling code reusable

modify/delete and rename/delete share a lot of similarities; we'd like all
the criss-cross and D/F conflict handling specializations to be shared
between the two.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Consider modifications in rename/rename(2to1) conflicts
Elijah Newren [Fri, 12 Aug 2011 05:20:18 +0000 (23:20 -0600)]
merge-recursive: Consider modifications in rename/rename(2to1) conflicts

Our previous conflict resolution for renaming two different files to the
same name ignored the fact that each of those files may have modifications
from both sides of history to consider.  We need to do a three-way merge
for each of those files, and then handle the conflict of both sets of
merged contents trying to be recorded with the same name.

It is important to note that this changes our strategy in the recursive
case.  After doing a three-way content merge of each of the files
involved, we still are faced with the fact that we are trying to put both
of the results (including conflict markers) into the same path.  We could
do another two-way merge, but I think that becomes confusing.  Also,
taking a hint from the modify/delete and rename/delete cases we handled
earlier, a more useful "common ground" would be to keep the three-way
content merge but record it with the original filename.  The renames can
still be detected, we just allow it to be done in the o->call_depth=0
case.  This seems to result in simpler & easier to understand merge
conflicts as well, as evidenced by some of the changes needed in our
testsuite in t6036.  (However, it should be noted that this change will
cause problems those renames also occur along with a file being added
whose name matches the source of the rename.  Since git currently cannot
detect rename/add-source situations, though, this codepath is not
currently used for those cases anyway.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Create function for merging with branchname:file markers
Elijah Newren [Fri, 12 Aug 2011 05:20:17 +0000 (23:20 -0600)]
merge-recursive: Create function for merging with branchname:file markers

We want to be able to reuse the code to do a three-way file content merge
and have the conflict markers use both branchname and filename.  Split it
out into a separate function.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Record more data needed for merging with dual renames
Elijah Newren [Fri, 12 Aug 2011 05:20:16 +0000 (23:20 -0600)]
merge-recursive: Record more data needed for merging with dual renames

When two different files are renamed to one, we need to be able to do
three-way merges for both of those files.  To do that, we need to record
the sha1sum of the (possibly modified) file on the unrenamed side.  Modify
setup_rename_conflict_info() to take this extra information and record it
when the rename_type is RENAME_TWO_FILES_TO_ONE.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Defer rename/rename(2to1) handling until process_entry
Elijah Newren [Fri, 12 Aug 2011 05:20:15 +0000 (23:20 -0600)]
merge-recursive: Defer rename/rename(2to1) handling until process_entry

This puts the code for the different types of double rename conflicts
closer together (fewer lines of other code separating the two paths) and
increases similarity between how they are handled.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Small cleanups for conflict_rename_rename_1to2
Elijah Newren [Fri, 12 Aug 2011 05:20:14 +0000 (23:20 -0600)]
merge-recursive: Small cleanups for conflict_rename_rename_1to2

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix rename/rename(1to2) resolution for virtual merge base
Elijah Newren [Fri, 12 Aug 2011 05:20:13 +0000 (23:20 -0600)]
merge-recursive: Fix rename/rename(1to2) resolution for virtual merge base

When renaming one file to two files, we really should be doing a content
merge.  Also, in the recursive case, undoing the renames and recording the
merged file in the index with the source of the rename (while deleting
both destinations) allows the renames to be re-detected in the
non-recursive merge and will result in fewer spurious conflicts.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Introduce a merge_file convenience function
Elijah Newren [Fri, 12 Aug 2011 05:20:12 +0000 (23:20 -0600)]
merge-recursive: Introduce a merge_file convenience function

merge_file previously required diff_filespec arguments, but all callers
only had sha1s and modes.  Rename merge_file to merge_file_1 and introduce
a new merge_file convenience function which takes the sha1s and modes and
creates the temporary diff_filespec variables needed to call merge_file_1.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix modify/delete resolution in the recursive case
Elijah Newren [Fri, 12 Aug 2011 05:20:11 +0000 (23:20 -0600)]
merge-recursive: Fix modify/delete resolution in the recursive case

When o->call_depth>0 and we have conflicts, we try to find "middle ground"
when creating the virtual merge base.  In the case of content conflicts,
this can be done by doing a three-way content merge and using the result.
In all parts where the three-way content merge is clean, it is the correct
middle ground, and in parts where it conflicts there is no middle ground
but the conflict markers provide a good compromise since they are unlikely
to accidentally match any further changes.

In the case of a modify/delete conflict, we cannot do the same thing.
Accepting either endpoint as the resolution for the virtual merge base
runs the risk that when handling the non-recursive case we will silently
accept one person's resolution over another without flagging a conflict.
In this case, the closest "middle ground" we have is actually the merge
base of the candidate merge bases.  (We could alternatively attempt a
three way content merge using an empty file in place of the deleted file,
but that seems to be more work than necessary.)

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: When we detect we can skip an update, actually skip it
Elijah Newren [Fri, 12 Aug 2011 05:20:10 +0000 (23:20 -0600)]
merge-recursive: When we detect we can skip an update, actually skip it

In 882fd11 (merge-recursive: Delay content merging for renames 2010-09-20),
there was code that checked for whether we could skip updating a file in
the working directory, based on whether the merged version matched the
current working copy.  Due to the desire to handle directory/file conflicts
that were resolvable, that commit deferred content merging by first
updating the index with the unmerged entries and then moving the actual
merging (along with the skip-the-content-update check) to another function
that ran later in the merge process.  As part moving the content merging
code, a bug was introduced such that although the message about skipping
the update would be printed (whenever GIT_MERGE_VERBOSITY was sufficiently
high), the file would be unconditionally updated in the working copy
anyway.

When we detect that the file does not need to be updated in the working
copy, update the index appropriately and then return early before updating
the working copy.

Note that there was a similar change in b2c8c0a (merge-recursive: When we
detect we can skip an update, actually skip it 2011-02-28), but it was
reverted by 6db4105 (Revert "Merge branch 'en/merge-recursive'"
2011-05-19) since it did not fix both of the relevant types of unnecessary
update breakages and, worse, it made use of some band-aids that caused
other problems.  The reason this change works is due to the changes earlier
in this series to (a) record_df_conflict_files instead of just unlinking
them early, (b) allowing make_room_for_path() to remove D/F entries,
(c) the splitting of update_stages_and_entry() to have its functionality
called at different points, and (d) making the pathnames of the files
involved in the merge available to merge_content().

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Provide more info in conflict markers with file renames
Elijah Newren [Fri, 12 Aug 2011 05:20:09 +0000 (23:20 -0600)]
merge-recursive: Provide more info in conflict markers with file renames

Whenever there are merge conflicts in file contents, we would mark the
different sides of the conflict with the two branches being merged.
However, when there is a rename involved as well, the branchname is not
sufficient to specify where the conflicting content came from.  In such
cases, mark the two sides of the conflict with branchname:filename rather
than just branchname.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Cleanup and consolidation of rename_conflict_info
Elijah Newren [Fri, 12 Aug 2011 05:20:08 +0000 (23:20 -0600)]
merge-recursive: Cleanup and consolidation of rename_conflict_info

The consolidation of process_entry() and process_df_entry() allows us to
consolidate more code paths concerning rename conflicts, and to do
a few additional related cleanups.  It also means we are using
rename_df_conflict_info in some cases where there is no D/F conflict;
rename it to rename_conflict_info.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Consolidate process_entry() and process_df_entry()
Elijah Newren [Fri, 12 Aug 2011 05:20:07 +0000 (23:20 -0600)]
merge-recursive: Consolidate process_entry() and process_df_entry()

The whole point of adding process_df_entry() was to ensure that files of
D/F conflicts were processed after paths under the corresponding
directory.  However, given that the entries are in sorted order, all we
need to do is iterate through them in reverse order to achieve the same
effect.  That lets us remove some duplicated code, and lets us keep
track of one less thing as we read the code ("do we need to make sure
this is processed before process_df_entry() or do we need to defer it
until then?").

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Improve handling of rename target vs. directory addition
Elijah Newren [Fri, 12 Aug 2011 05:20:06 +0000 (23:20 -0600)]
merge-recursive: Improve handling of rename target vs. directory addition

When dealing with file merging and renames and D/F conflicts and possible
criss-cross merges (how's that for a corner case?), we did not do a
thorough job ensuring the index and working directory had the correct
contents.   Fix the logic in merge_content() to handle this.  Also,
correct some erroneous tests in t6022 that were expecting the wrong number
of unmerged index entries.  These changes fix one of the tests in t6042
(and almost fix another one from t6042 as well).

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Add comments about handling rename/add-source cases
Elijah Newren [Fri, 12 Aug 2011 05:20:05 +0000 (23:20 -0600)]
merge-recursive: Add comments about handling rename/add-source cases

There are a couple of places where changes are needed to for situations
involving rename/add-source issues.  Add comments about the needed changes
(and existing bugs) until git has been enabled to detect such cases.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Make dead code for rename/rename(2to1) conflicts undead
Elijah Newren [Fri, 12 Aug 2011 05:20:04 +0000 (23:20 -0600)]
merge-recursive: Make dead code for rename/rename(2to1) conflicts undead

The code for rename_rename_2to1 conflicts (two files both being renamed to
the same filename) was dead since the rename/add path was always being
independently triggered for each of the renames instead.  Further,
reviving the dead code showed that it was inherently buggy and would
always segfault -- among a few other bugs.

Move the else-if branch for the rename/rename block before the rename/add
block to make sure it is checked first, and fix up the rename/rename(2to1)
code segments to make it handle most cases.  Work is still needed to
handle higher dimensional corner cases such as rename/rename/modify/modify
issues.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix deletion of untracked file in rename/delete conflicts
Elijah Newren [Fri, 12 Aug 2011 05:20:03 +0000 (23:20 -0600)]
merge-recursive: Fix deletion of untracked file in rename/delete conflicts

In the recursive case (o->call_depth > 0), we do not modify the working
directory.  However, when o->call_depth==0, file renames can mean we need
to delete the old filename from the working copy.  Since there have been
lots of changes and mistakes here, let's go through the details.  Let's
start with a simple explanation of what we are trying to achieve:

  Original goal: If a file is renamed on the side of history being merged
  into head, the filename serving as the source of that rename needs to be
  removed from the working directory.

The path to getting the above statement implemented in merge-recursive took
several steps.  The relevant bits of code may be instructive to keep in
mind for the explanation, especially since an English-only description
involves double negatives that are hard to follow.  These bits of code are:
  int remove_file(..., const char *path, int no_wd)
  {
    ...
    int update_working_directory = !o->call_depth && !no_wd;
and
  remove_file(o, 1, ren1_src, <expression>);
Where the choice for <expression> has morphed over time:

65ac6e9 (merge-recursive: adjust to loosened "working file clobbered"
check 2006-10-27), introduced the "no_wd" parameter to remove_file() and
used "1" for <expression>.  This meant ren1_src was never deleted, leaving
it around in the working copy.

In 8371234 (Remove uncontested renamed files during merge. 2006-12-13),
<expression> was changed to "index_only" (where index_only ==
!!o->call_depth; see b7fa51da).   This was equivalent to using "0" for
<expression> (due to the early logic in remove_file), and is orthogonal to
the condition we actually want to check at this point; it resulted in the
source file being removed except when index_only was false.  This was
problematic because the file could have been renamed on the side of history
including head, in which case ren1_src could correspond to an untracked
file that should not be deleted.

In 183d797 (Keep untracked files not involved in a merge. 2007-02-04),
<expression> was changed to "index_only || stage == 3".  While this gives
correct behavior, the "index_only ||" portion of <expression> is
unnecessary and makes the code slightly harder to follow.

There were also two further changes to this expression, though without
any change in behavior.  First in b7fa51d (merge-recursive: get rid of the
index_only global variable 2008-09-02), it was changed to "o->call_depth
|| stage == 3".  (index_only == !!o->call_depth).  Later, in 41d70bd6
(merge-recursive: Small code clarification -- variable name and comments),
this was changed to "o->call_depth || renamed_stage == 2" (where stage was
renamed to other_stage and renamed_stage == other_stage ^ 1).

So we ended with <expression> being "o->call_depth || renamed_stage == 2".
But the "o->call_depth ||" piece was unnecessary.  We can remove it,
leaving us with <expression> being "renamed_stage == 2".  This doesn't
change behavior at all, but it makes the code clearer.  Which is good,
because it's about to get uglier.

  Corrected goal: If a file is renamed on the side of history being merged
  into head, the filename serving as the source of that rename needs to be
  removed from the working directory *IF* that file is tracked in head AND
  the file tracked in head is related to the original file.

Note that the only difference between the original goal and the corrected
goal is the two extra conditions added at the end.  The first condition is
relevant in a rename/delete conflict.  If the file was deleted on the
HEAD side of the merge and an untracked file of the same name was added to
the working copy, then without that extra condition the untracked file
will be erroneously deleted.  This changes <expression> to "renamed_stage
== 2 || !was_tracked(ren1_src)".

The second additional condition is relevant in two cases.

The first case the second condition can occur is when a file is deleted
and a completely different file is added with the same name.  To my
knowledge, merge-recursive has no mechanism for detecting deleted-and-
replaced-by-different-file cases, so I am simply punting on this
possibility.

The second case for the second condition to occur is when there is a
rename/rename/add-source conflict.  That is, when the original file was
renamed on both sides of history AND the original filename is being
re-used by some unrelated (but tracked) content.  This case also presents
some additional difficulties for us since we cannot currently detect these
rename/rename/add-source conflicts; as long as the rename detection logic
"optimizes" by ignoring filenames that are present at both ends of the
diff, these conflicts will go unnoticed.  However, rename/rename conflicts
are handled by an entirely separate codepath not being discussed here, so
this case is not relevant for the line of code under consideration.

In summary:
  Change <expression> from "o->call_depth || renamed_stage == 2" to
  "renamed_stage == 2 || !was_tracked(ren1_src)", in order to remove
  unnecessary code and avoid deleting untracked files.

96 lines of explanation in the changelog to describe a one-line fix...

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Split update_stages_and_entry; only update stages at end
Elijah Newren [Fri, 12 Aug 2011 05:20:02 +0000 (23:20 -0600)]
merge-recursive: Split update_stages_and_entry; only update stages at end

Instead of having the process_renames logic update the stages in the index
for the rename destination, have the index updated after process_entry or
process_df_entry.  This will also allow us to have process_entry determine
whether a file was tracked and existed in the working copy before the
merge started.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Allow make_room_for_path() to remove D/F entries
Elijah Newren [Fri, 12 Aug 2011 05:20:01 +0000 (23:20 -0600)]
merge-recursive: Allow make_room_for_path() to remove D/F entries

If there were several files conflicting below a directory corresponding
to a D/F conflict, and the file of that D/F conflict is in the way, we
want it to be removed.  Since files of D/F conflicts are handled last,
they can be reinstated later and possibly with a new unique name.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agostring-list: Add API to remove an item from an unsorted list
Johannes Sixt [Fri, 12 Aug 2011 05:20:00 +0000 (23:20 -0600)]
string-list: Add API to remove an item from an unsorted list

Teach the string-list API how to remove an entry in O(1) runtime by
moving the last entry to the vacated spot. As such, the routine works
only for unsorted lists.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Split was_tracked() out of would_lose_untracked()
Elijah Newren [Fri, 12 Aug 2011 05:19:59 +0000 (23:19 -0600)]
merge-recursive: Split was_tracked() out of would_lose_untracked()

Checking whether a filename was part of stage 0 or stage 2 is code that we
would like to be able to call from a few other places without also
lstat()-ing the file to see if it exists in the working copy.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Save D/F conflict filenames instead of unlinking them
Elijah Newren [Fri, 12 Aug 2011 05:19:58 +0000 (23:19 -0600)]
merge-recursive: Save D/F conflict filenames instead of unlinking them

Rename make_room_for_directories_of_df_conflicts() to
record_df_conflict_files() to reflect the change in functionality.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix code checking for D/F conflicts still being present
Elijah Newren [Fri, 12 Aug 2011 05:19:57 +0000 (23:19 -0600)]
merge-recursive: Fix code checking for D/F conflicts still being present

Previously, we were using lstat() to determine if a directory was still
present after a merge (and thus in the way of adding a file).  We should
have been using lstat() only to determine if untracked directories were in
the way (and then only when necessary to check for untracked directories);
we should instead using the index to determine if there is a tracked
directory in the way.  Create a new function to do this and use it to
replace the existing checks for directories being in the way.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix sorting order and directory change assumptions
Elijah Newren [Fri, 12 Aug 2011 05:19:56 +0000 (23:19 -0600)]
merge-recursive: Fix sorting order and directory change assumptions

We cannot assume that directory/file conflicts will appear in sorted
order; for example, 'letters.txt' comes between 'letters' and
'letters/file'.

Thanks to Johannes for a pointer about qsort stability issues with
Windows and suggested code change.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Fix recursive case with D/F conflict via add/add conflict
Elijah Newren [Fri, 12 Aug 2011 05:19:55 +0000 (23:19 -0600)]
merge-recursive: Fix recursive case with D/F conflict via add/add conflict

When a D/F conflict is introduced via an add/add conflict, when
o->call_depth > 0 we need to ensure that the higher stage entry from the
base stage is removed.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Avoid working directory changes during recursive case
Elijah Newren [Fri, 12 Aug 2011 05:19:54 +0000 (23:19 -0600)]
merge-recursive: Avoid working directory changes during recursive case

make_room_for_directories_of_df_conflicts() is about making sure necessary
working directory changes can succeed.  When o->call_depth > 0 (i.e. the
recursive case), we do not want to make any working directory changes so
this function should be skipped.

Note that make_room_for_directories_of_df_conflicts() is broken as has
been pointed out by Junio; it should NOT be unlinking files.  What it
should do is keep track of files that could be unlinked if a directory
later needs to be written in their place.  However, that work also is only
relevant in the non-recursive case, so this change is helpful either way.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Remember to free generated unique path names
Elijah Newren [Fri, 12 Aug 2011 05:19:53 +0000 (23:19 -0600)]
merge-recursive: Remember to free generated unique path names

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Consolidate different update_stages functions
Elijah Newren [Fri, 12 Aug 2011 05:19:52 +0000 (23:19 -0600)]
merge-recursive: Consolidate different update_stages functions

We are only calling update_stages_options() one way really, so we can
consolidate the slightly different variants into one and remove some
parameters whose values are always the same.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Mark some diff_filespec struct arguments const
Elijah Newren [Fri, 12 Aug 2011 05:19:51 +0000 (23:19 -0600)]
merge-recursive: Mark some diff_filespec struct arguments const

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 years agomerge-recursive: Correct a comment
Elijah Newren [Fri, 12 Aug 2011 05:19:50 +0000 (23:19 -0600)]
merge-recursive: Correct a comment

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>