annotate lib/git-merge-changelog.c @ 18065:fd4663ad7454

time_rz: port to Solaris etc. Works around a tzname problem on platforms like Solaris that have tzname but not tm_zone, by setting tzname at the appropriate time and restoring it later. * lib/time_rz.c (tzname_address, tzname_value) [HAVE_TZNAME]: New static vars. (save_abbr) [HAVE_TZNAME]: Set them. (revert_tz) [HAVE_TZNAME]: Clear or use them. (restore_tzname): New function. (localtime_rz, mktime_z): Use it.
author Paul Eggert <eggert@cs.ucla.edu>
date Sat, 25 Jul 2015 15:20:10 -0700
parents d09167851e07
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1 /* git-merge-changelog - git "merge" driver for GNU style ChangeLog files.
13364
f07c1f071ff0 git-merge-changelog: Enable --split-merged-entry by default.
Bruno Haible <bruno@clisp.org>
parents: 12445
diff changeset
2 Copyright (C) 2008-2010 Bruno Haible <bruno@clisp.org>
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
4 This program is free software: you can redistribute it and/or modify
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
6 the Free Software Foundation; either version 2 of the License, or
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
7 (at your option) any later version.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
8
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
12 GNU General Public License for more details.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
13
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
16
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17 /* README:
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18 The default merge driver of 'git' *always* produces conflicts when
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19 pulling public modifications into a privately modified ChangeLog file.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20 This is because ChangeLog files are always modified at the top; the
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21 default merge driver has no clue how to deal with this. Furthermore
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22 the conflicts are presented with more <<<< ==== >>>> markers than
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23 necessary; this is because the default merge driver makes pointless
11410
3c2e2d1bd42c Typo in comment.
Bruno Haible <bruno@clisp.org>
parents: 10092
diff changeset
24 efforts to look at the individual line changes inside a ChangeLog entry.
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
25
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
26 This program serves as a 'git' merge driver that avoids these problems.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
27 1. It produces no conflict when ChangeLog entries have been inserted
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
28 at the top both in the public and in the private modification. It
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
29 puts the privately added entries above the publicly added entries.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
30 2. It respects the structure of ChangeLog files: entries are not split
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
31 into lines but kept together.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
32 3. It also handles the case of small modifications of past ChangeLog
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
33 entries, or of removed ChangeLog entries: they are merged as one
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
34 would expect it.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
35 4. Conflicts are presented at the top of the file, rather than where
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
36 they occurred, so that the user will see them immediately. (Unlike
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
37 for source code written in some programming language, conflict markers
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
38 that are located several hundreds lines from the top will not cause
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
39 any syntax error and therefore would be likely to remain unnoticed.)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
40 */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
41
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
42 /* Installation:
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
43
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
44 $ gnulib-tool --create-testdir --dir=/tmp/testdir123 git-merge-changelog
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
45 $ cd /tmp/testdir123
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
46 $ ./configure
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
47 $ make
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
48 $ make install
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
49
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
50 Additionally, for git users:
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
51 - Add to .git/config of the checkout (or to your $HOME/.gitconfig) the
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
52 lines
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
53
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
54 [merge "merge-changelog"]
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
55 name = GNU-style ChangeLog merge driver
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
56 driver = /usr/local/bin/git-merge-changelog %O %A %B
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
57
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
58 - In every directory that contains a ChangeLog file, add a file
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
59 '.gitattributes' with this line:
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
60
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
61 ChangeLog merge=merge-changelog
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
62
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
63 (See "man 5 gitattributes" for more info.)
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
64
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
65 Additionally, for bzr users:
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
66 - Install the 'extmerge' bzr plug-in listed at
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
67 <http://doc.bazaar.canonical.com/plugins/en/index.html>
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
68 <http://wiki.bazaar.canonical.com/BzrPlugins>
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
69 - Add to your $HOME/.bazaar/bazaar.conf the line
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
70
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
71 external_merge = git-merge-changelog %b %T %o
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
72
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
73 - Then, to merge a conflict in a ChangeLog file, use
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
74
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
75 $ bzr extmerge ChangeLog
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
76
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
77 Additionally, for hg users:
16708
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
78 - Add to your $HOME/.hgrc the lines
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
79
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
80 [merge-patterns]
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
81 ChangeLog = git-merge-changelog
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
82
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
83 [merge-tools]
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
84 git-merge-changelog.executable = /usr/local/bin/git-merge-changelog
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
85 git-merge-changelog.args = $base $local $other
1699b04c1c45 git-merge-changelog: add specific example on how to use with hg.
Mark Wielaard <mark@klomp.org>
parents: 16707
diff changeset
86
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
87 See <http://www.selenic.com/mercurial/hgrc.5.html> section merge-tools
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
88 for reference.
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
89 */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
90
13551
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
91 /* Use as an alternative to 'diff3':
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
92 git-merge-changelog performs the same role as "diff3 -m", just with
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
93 reordered arguments:
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
94 $ git-merge-changelog %O %A %B
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
95 is comparable to
666f1b5963c2 git-merge-changelog: add doc relating to use with bzr and hg.
Brian Gough <bjg@gnu.org>
parents: 13364
diff changeset
96 $ diff3 -m %A %O %B
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
97 */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
98
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
99 /* Calling convention:
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
100 A merge driver is called with three filename arguments:
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
101 1. %O = The common ancestor of %A and %B.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
102 2. %A = The file's contents from the "current branch".
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
103 3. %B = The file's contents from the "other branch"; this is the contents
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
104 being merged in.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
105
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
106 In case of a "git stash apply" or of an upstream pull (e.g. from a subsystem
9710
b2e9096015d9 Support the "git pull --rebase" situation.
Bruno Haible <bruno@clisp.org>
parents: 9693
diff changeset
107 maintainer to a central maintainer) or of a downstream pull with --rebase:
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
108 2. %A = The file's newest pulled contents; modified by other committers.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
109 3. %B = The user's newest copy of the file; modified by the user.
9710
b2e9096015d9 Support the "git pull --rebase" situation.
Bruno Haible <bruno@clisp.org>
parents: 9693
diff changeset
110 In case of a downstream pull (e.g. from a central repository to the user)
b2e9096015d9 Support the "git pull --rebase" situation.
Bruno Haible <bruno@clisp.org>
parents: 9693
diff changeset
111 or of an upstream pull with --rebase:
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
112 2. %A = The user's newest copy of the file; modified by the user.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
113 3. %B = The file's newest pulled contents; modified by other committers.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
114
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
115 It should write its merged output into file %A. It can also echo some
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
116 remarks to stdout. It should exit with return code 0 if the merge could
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
117 be resolved cleanly, or with non-zero return code if there were conflicts.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
118 */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
119
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
120 /* How it works:
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
121 The structure of a ChangeLog file: It consists of ChangeLog entries. A
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
122 ChangeLog entry starts at a line following a blank line and that starts with
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
123 a non-whitespace character, or at the beginning of a file.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
124 The merge driver works as follows: It reads the three files into memory and
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
125 dissects them into ChangeLog entries. It then finds the differences between
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
126 %O and %B. They are classified as:
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
127 - removals (some consecutive entries removed),
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
128 - changes (some consecutive entries removed, some consecutive entries
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
129 added),
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
130 - additions (some consecutive entries added).
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
131 The driver then attempts to apply the changes to %A.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
132 To this effect, it first computes a correspondence between the entries in %O
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
133 and the entries in %A, using fuzzy string matching to still identify changed
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
134 entries.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
135 - Removals are applied one by one. If the entry is present in %A, at any
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
136 position, it is removed. If not, the removal is marked as a conflict.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
137 - Additions at the top of %B are applied at the top of %A.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
138 - Additions between entry x and entry y (y may be the file end) in %B are
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
139 applied between entry x and entry y in %A (if they still exist and are
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
140 still consecutive in %A), otherwise the additions are marked as a
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
141 conflict.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
142 - Changes are categorized into "simple changes":
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
143 entry1 ... entryn
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
144 are mapped to
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
145 added_entry ... added_entry modified_entry1 ... modified_entryn,
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
146 where the correspondence between entry_i and modified_entry_i is still
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
147 clear; and "big changes": these are all the rest. Simple changes at the
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
148 top of %B are applied by putting the added entries at the top of %A. The
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
149 changes in simple changes are applied one by one; possibly leading to
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
150 single-entry conflicts. Big changes are applied en bloc, possibly
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
151 leading to conflicts spanning multiple entries.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
152 - Conflicts are output at the top of the file and cause an exit status of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
153 1.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
154 */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
155
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
156 #include <config.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
157
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
158 #include <getopt.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
159 #include <limits.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
160 #include <stdbool.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
161 #include <stdio.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
162 #include <stdlib.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
163 #include <string.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
164 #include <sys/types.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
165 #include <unistd.h>
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
166
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
167 #include "progname.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
168 #include "error.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
169 #include "read-file.h"
12445
a8c91b846640 Move the malloc checking from module 'list' to new module 'xlist'.
Bruno Haible <bruno@clisp.org>
parents: 12421
diff changeset
170 #include "gl_xlist.h"
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
171 #include "gl_array_list.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
172 #include "gl_linkedhash_list.h"
9712
a49ca512452c Speed up from O(n^2) to O(n).
Bruno Haible <bruno@clisp.org>
parents: 9711
diff changeset
173 #include "gl_rbtreehash_list.h"
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
174 #include "gl_linked_list.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
175 #include "xalloc.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
176 #include "xmalloca.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
177 #include "fstrcmp.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
178 #include "minmax.h"
9710
b2e9096015d9 Support the "git pull --rebase" situation.
Bruno Haible <bruno@clisp.org>
parents: 9693
diff changeset
179 #include "c-strstr.h"
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
180 #include "fwriteerror.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
181
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
182 #define ASSERT(expr) \
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
183 do \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
184 { \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
185 if (!(expr)) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
186 abort (); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
187 } \
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
188 while (0)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
189
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
190 #define FSTRCMP_THRESHOLD 0.6
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
191 #define FSTRCMP_STRICTER_THRESHOLD 0.8
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
192
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
193 /* Representation of a ChangeLog entry.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
194 The string may contain NUL bytes; therefore it is represented as a plain
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
195 opaque memory region. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
196 struct entry
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
197 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
198 char *string;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
199 size_t length;
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
200 /* Cache for the hash code. */
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
201 bool hashcode_cached;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
202 size_t hashcode;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
203 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
204
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
205 /* Create an entry.
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
206 The memory region passed by the caller must of indefinite extent. It is
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
207 *not* copied here. */
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
208 static struct entry *
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
209 entry_create (char *string, size_t length)
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
210 {
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
211 struct entry *result = XMALLOC (struct entry);
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
212 result->string = string;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
213 result->length = length;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
214 result->hashcode_cached = false;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
215 return result;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
216 }
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
217
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
218 /* Compare two entries for equality. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
219 static bool
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
220 entry_equals (const void *elt1, const void *elt2)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
221 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
222 const struct entry *entry1 = (const struct entry *) elt1;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
223 const struct entry *entry2 = (const struct entry *) elt2;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
224 return entry1->length == entry2->length
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
225 && memcmp (entry1->string, entry2->string, entry1->length) == 0;
9909
adb9a924703b Remove stray semicolon.
Bruno Haible <bruno@clisp.org>
parents: 9715
diff changeset
226 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
227
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
228 /* Return a hash code of the contents of a ChangeLog entry. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
229 static size_t
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
230 entry_hashcode (const void *elt)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
231 {
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
232 struct entry *entry = (struct entry *) elt;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
233 if (!entry->hashcode_cached)
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
234 {
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
235 /* See http://www.haible.de/bruno/hashfunc.html. */
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
236 const char *s;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
237 size_t n;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
238 size_t h = 0;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
239
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
240 for (s = entry->string, n = entry->length; n > 0; s++, n--)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
241 h = (unsigned char) *s + ((h << 9) | (h >> (sizeof (size_t) * CHAR_BIT - 9)));
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
242
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
243 entry->hashcode = h;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
244 entry->hashcode_cached = true;
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
245 }
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
246 return entry->hashcode;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
247 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
248
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
249 /* Perform a fuzzy comparison of two ChangeLog entries.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
250 Return a similarity measure of the two entries, a value between 0 and 1.
11704
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
251 0 stands for very distinct, 1 for identical.
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
252 If the result is < LOWER_BOUND, an arbitrary other value < LOWER_BOUND can
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
253 be returned. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
254 static double
11704
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
255 entry_fstrcmp (const struct entry *entry1, const struct entry *entry2,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
256 double lower_bound)
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
257 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
258 /* fstrcmp works only on NUL terminated strings. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
259 char *memory;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
260 double similarity;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
261
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
262 if (memchr (entry1->string, '\0', entry1->length) != NULL)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
263 return 0.0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
264 if (memchr (entry2->string, '\0', entry2->length) != NULL)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
265 return 0.0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
266 memory = (char *) xmalloca (entry1->length + 1 + entry2->length + 1);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
267 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
268 char *p = memory;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
269 memcpy (p, entry1->string, entry1->length);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
270 p += entry1->length;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
271 *p++ = '\0';
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
272 memcpy (p, entry2->string, entry2->length);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
273 p += entry2->length;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
274 *p++ = '\0';
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
275 }
11704
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
276 similarity =
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
277 fstrcmp_bounded (memory, memory + entry1->length + 1, lower_bound);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
278 freea (memory);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
279 return similarity;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
280 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
281
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
282 /* This structure represents an entire ChangeLog file, after it was read
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
283 into memory. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
284 struct changelog_file
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
285 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
286 /* The entries, as a list. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
287 gl_list_t /* <struct entry *> */ entries_list;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
288 /* The entries, as a list in opposite direction. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
289 gl_list_t /* <struct entry *> */ entries_reversed;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
290 /* The entries, as an array. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
291 size_t num_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
292 struct entry **entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
293 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
294
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
295 /* Read a ChangeLog file into memory.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
296 Return the contents in *RESULT. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
297 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
298 read_changelog_file (const char *filename, struct changelog_file *result)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
299 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
300 /* Read the file in text mode, otherwise it's hard to recognize empty
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
301 lines. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
302 size_t length;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
303 char *contents = read_file (filename, &length);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
304 if (contents == NULL)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
305 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
306 fprintf (stderr, "could not read file '%s'\n", filename);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
307 exit (EXIT_FAILURE);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
308 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
309
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
310 result->entries_list =
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
311 gl_list_create_empty (GL_LINKEDHASH_LIST, entry_equals, entry_hashcode,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
312 NULL, true);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
313 result->entries_reversed =
9712
a49ca512452c Speed up from O(n^2) to O(n).
Bruno Haible <bruno@clisp.org>
parents: 9711
diff changeset
314 gl_list_create_empty (GL_RBTREEHASH_LIST, entry_equals, entry_hashcode,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
315 NULL, true);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
316 /* A ChangeLog file consists of ChangeLog entries. A ChangeLog entry starts
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
317 at a line following a blank line and that starts with a non-whitespace
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
318 character, or at the beginning of a file.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
319 Split the file contents into entries. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
320 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
321 char *contents_end = contents + length;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
322 char *start = contents;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
323 while (start < contents_end)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
324 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
325 /* Search the end of the current entry. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
326 char *ptr = start;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
327 struct entry *curr;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
328
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
329 while (ptr < contents_end)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
330 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
331 ptr = memchr (ptr, '\n', contents_end - ptr);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
332 if (ptr == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
333 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
334 ptr = contents_end;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
335 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
336 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
337 ptr++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
338 if (contents_end - ptr >= 2
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
339 && ptr[0] == '\n'
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
340 && !(ptr[1] == '\n' || ptr[1] == '\t' || ptr[1] == ' '))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
341 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
342 ptr++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
343 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
344 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
345 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
346
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
347 curr = entry_create (start, ptr - start);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
348 gl_list_add_last (result->entries_list, curr);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
349 gl_list_add_first (result->entries_reversed, curr);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
350
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
351 start = ptr;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
352 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
353 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
354
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
355 result->num_entries = gl_list_size (result->entries_list);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
356 result->entries = XNMALLOC (result->num_entries, struct entry *);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
357 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
358 size_t index = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
359 gl_list_iterator_t iter = gl_list_iterator (result->entries_list);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
360 const void *elt;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
361 gl_list_node_t node;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
362 while (gl_list_iterator_next (&iter, &elt, &node))
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
363 result->entries[index++] = (struct entry *) elt;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
364 gl_list_iterator_free (&iter);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
365 ASSERT (index == result->num_entries);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
366 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
367 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
368
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
369 /* A mapping (correspondence) between entries of FILE1 and of FILE2. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
370 struct entries_mapping
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
371 {
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
372 struct changelog_file *file1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
373 struct changelog_file *file2;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
374 /* Mapping from indices in FILE1 to indices in FILE2.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
375 A value -1 means that the entry from FILE1 is not found in FILE2.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
376 A value -2 means that it has not yet been computed. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
377 ssize_t *index_mapping;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
378 /* Mapping from indices in FILE2 to indices in FILE1.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
379 A value -1 means that the entry from FILE2 is not found in FILE1.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
380 A value -2 means that it has not yet been computed. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
381 ssize_t *index_mapping_reverse;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
382 };
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
383
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
384 /* Look up (or lazily compute) the mapping of an entry in FILE1.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
385 i is the index in FILE1.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
386 Return the index in FILE2, or -1 when the entry is not found in FILE2. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
387 static ssize_t
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
388 entries_mapping_get (struct entries_mapping *mapping, ssize_t i)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
389 {
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
390 if (mapping->index_mapping[i] < -1)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
391 {
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
392 struct changelog_file *file1 = mapping->file1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
393 struct changelog_file *file2 = mapping->file2;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
394 size_t n1 = file1->num_entries;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
395 size_t n2 = file2->num_entries;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
396 struct entry *entry_i = file1->entries[i];
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
397 ssize_t j;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
398
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
399 /* Search whether it approximately occurs in file2. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
400 ssize_t best_j = -1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
401 double best_j_similarity = 0.0;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
402 for (j = n2 - 1; j >= 0; j--)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
403 if (mapping->index_mapping_reverse[j] < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
404 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
405 double similarity =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
406 entry_fstrcmp (entry_i, file2->entries[j], best_j_similarity);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
407 if (similarity > best_j_similarity)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
408 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
409 best_j = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
410 best_j_similarity = similarity;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
411 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
412 }
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
413 if (best_j_similarity >= FSTRCMP_THRESHOLD)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
414 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
415 /* Found a similar entry in file2. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
416 struct entry *entry_j = file2->entries[best_j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
417 /* Search whether it approximately occurs in file1 at index i. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
418 ssize_t best_i = -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
419 double best_i_similarity = 0.0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
420 ssize_t ii;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
421 for (ii = n1 - 1; ii >= 0; ii--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
422 if (mapping->index_mapping[ii] < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
423 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
424 double similarity =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
425 entry_fstrcmp (file1->entries[ii], entry_j,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
426 best_i_similarity);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
427 if (similarity > best_i_similarity)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
428 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
429 best_i = ii;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
430 best_i_similarity = similarity;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
431 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
432 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
433 if (best_i_similarity >= FSTRCMP_THRESHOLD && best_i == i)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
434 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
435 mapping->index_mapping[i] = best_j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
436 mapping->index_mapping_reverse[best_j] = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
437 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
438 }
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
439 if (mapping->index_mapping[i] < -1)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
440 /* It does not approximately occur in FILE2.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
441 Remember it, for next time. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
442 mapping->index_mapping[i] = -1;
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
443 }
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
444 return mapping->index_mapping[i];
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
445 }
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
446
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
447 /* Look up (or lazily compute) the mapping of an entry in FILE2.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
448 j is the index in FILE2.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
449 Return the index in FILE1, or -1 when the entry is not found in FILE1. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
450 static ssize_t
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
451 entries_mapping_reverse_get (struct entries_mapping *mapping, ssize_t j)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
452 {
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
453 if (mapping->index_mapping_reverse[j] < -1)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
454 {
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
455 struct changelog_file *file1 = mapping->file1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
456 struct changelog_file *file2 = mapping->file2;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
457 size_t n1 = file1->num_entries;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
458 size_t n2 = file2->num_entries;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
459 struct entry *entry_j = file2->entries[j];
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
460 ssize_t i;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
461
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
462 /* Search whether it approximately occurs in file1. */
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
463 ssize_t best_i = -1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
464 double best_i_similarity = 0.0;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
465 for (i = n1 - 1; i >= 0; i--)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
466 if (mapping->index_mapping[i] < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
467 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
468 double similarity =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
469 entry_fstrcmp (file1->entries[i], entry_j, best_i_similarity);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
470 if (similarity > best_i_similarity)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
471 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
472 best_i = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
473 best_i_similarity = similarity;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
474 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
475 }
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
476 if (best_i_similarity >= FSTRCMP_THRESHOLD)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
477 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
478 /* Found a similar entry in file1. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
479 struct entry *entry_i = file1->entries[best_i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
480 /* Search whether it approximately occurs in file2 at index j. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
481 ssize_t best_j = -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
482 double best_j_similarity = 0.0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
483 ssize_t jj;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
484 for (jj = n2 - 1; jj >= 0; jj--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
485 if (mapping->index_mapping_reverse[jj] < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
486 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
487 double similarity =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
488 entry_fstrcmp (entry_i, file2->entries[jj],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
489 best_j_similarity);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
490 if (similarity > best_j_similarity)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
491 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
492 best_j = jj;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
493 best_j_similarity = similarity;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
494 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
495 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
496 if (best_j_similarity >= FSTRCMP_THRESHOLD && best_j == j)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
497 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
498 mapping->index_mapping_reverse[j] = best_i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
499 mapping->index_mapping[best_i] = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
500 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
501 }
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
502 if (mapping->index_mapping_reverse[j] < -1)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
503 /* It does not approximately occur in FILE1.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
504 Remember it, for next time. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
505 mapping->index_mapping_reverse[j] = -1;
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
506 }
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
507 return mapping->index_mapping_reverse[j];
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
508 }
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
509
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
510 /* Compute a mapping (correspondence) between entries of FILE1 and of FILE2.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
511 The correspondence also takes into account small modifications; i.e. the
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
512 indicated relation is not equality of entries but best-match similarity
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
513 of entries.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
514 If FULL is true, the maximum of matching is done up-front. If it is false,
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
515 it is done in a lazy way through the functions entries_mapping_get and
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
516 entries_mapping_reverse_get.
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
517 Return the result in *RESULT. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
518 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
519 compute_mapping (struct changelog_file *file1, struct changelog_file *file2,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
520 bool full,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
521 struct entries_mapping *result)
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
522 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
523 /* Mapping from indices in file1 to indices in file2. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
524 ssize_t *index_mapping;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
525 /* Mapping from indices in file2 to indices in file1. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
526 ssize_t *index_mapping_reverse;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
527 size_t n1 = file1->num_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
528 size_t n2 = file2->num_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
529 ssize_t i, j;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
530
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
531 index_mapping = XNMALLOC (n1, ssize_t);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
532 for (i = 0; i < n1; i++)
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
533 index_mapping[i] = -2;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
534
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
535 index_mapping_reverse = XNMALLOC (n2, ssize_t);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
536 for (j = 0; j < n2; j++)
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
537 index_mapping_reverse[j] = -2;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
538
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
539 for (i = n1 - 1; i >= 0; i--)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
540 /* Take an entry from file1. */
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
541 if (index_mapping[i] < -1)
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
542 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
543 struct entry *entry = file1->entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
544 /* Search whether it occurs in file2. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
545 j = gl_list_indexof (file2->entries_reversed, entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
546 if (j >= 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
547 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
548 j = n2 - 1 - j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
549 /* Found an exact correspondence. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
550 /* If index_mapping_reverse[j] >= 0, we have already seen other
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
551 copies of this entry, and there were more occurrences of it in
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
552 file1 than in file2. In this case, do nothing. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
553 if (index_mapping_reverse[j] < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
554 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
555 index_mapping[i] = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
556 index_mapping_reverse[j] = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
557 /* Look for more occurrences of the same entry. Match them
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
558 as long as they pair up. Unpaired occurrences of the same
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
559 entry are left without mapping. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
560 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
561 ssize_t curr_i = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
562 ssize_t curr_j = j;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
563
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
564 for (;;)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
565 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
566 ssize_t next_i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
567 ssize_t next_j;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
568
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
569 next_i =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
570 gl_list_indexof_from (file1->entries_reversed,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
571 n1 - curr_i, entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
572 if (next_i < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
573 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
574 next_j =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
575 gl_list_indexof_from (file2->entries_reversed,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
576 n2 - curr_j, entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
577 if (next_j < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
578 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
579 curr_i = n1 - 1 - next_i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
580 curr_j = n2 - 1 - next_j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
581 ASSERT (index_mapping[curr_i] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
582 ASSERT (index_mapping_reverse[curr_j] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
583 index_mapping[curr_i] = curr_j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
584 index_mapping_reverse[curr_j] = curr_i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
585 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
586 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
587 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
588 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
589 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
590
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
591 result->file1 = file1;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
592 result->file2 = file2;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
593 result->index_mapping = index_mapping;
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
594 result->index_mapping_reverse = index_mapping_reverse;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
595
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
596 if (full)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
597 for (i = n1 - 1; i >= 0; i--)
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
598 entries_mapping_get (result, i);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
599 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
600
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
601 /* An "edit" is a textual modification performed by the user, that needs to
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
602 be applied to the other file. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
603 enum edit_type
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
604 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
605 /* Some consecutive entries were added. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
606 ADDITION,
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
607 /* Some consecutive entries were removed; some other consecutive entries
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
608 were added at the same position. (Not necessarily the same number of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
609 entries.) */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
610 CHANGE,
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
611 /* Some consecutive entries were removed. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
612 REMOVAL
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
613 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
614
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
615 /* This structure represents an edit. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
616 struct edit
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
617 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
618 enum edit_type type;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
619 /* Range of indices into the entries of FILE1. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
620 ssize_t i1, i2; /* first, last index; only used for CHANGE, REMOVAL */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
621 /* Range of indices into the entries of FILE2. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
622 ssize_t j1, j2; /* first, last index; only used for ADDITION, CHANGE */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
623 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
624
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
625 /* This structure represents the differences from one file, FILE1, to another
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
626 file, FILE2. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
627 struct differences
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
628 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
629 /* An array mapping FILE1 indices to FILE2 indices (or -1 when the entry
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
630 from FILE1 is not found in FILE2). */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
631 ssize_t *index_mapping;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
632 /* An array mapping FILE2 indices to FILE1 indices (or -1 when the entry
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
633 from FILE2 is not found in FILE1). */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
634 ssize_t *index_mapping_reverse;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
635 /* The edits that transform FILE1 into FILE2. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
636 size_t num_edits;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
637 struct edit **edits;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
638 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
639
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
640 /* Import the difference detection algorithm from GNU diff. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
641 #define ELEMENT struct entry *
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
642 #define EQUAL entry_equals
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
643 #define OFFSET ssize_t
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
644 #define EXTRA_CONTEXT_FIELDS \
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
645 ssize_t *index_mapping; \
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
646 ssize_t *index_mapping_reverse;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
647 #define NOTE_DELETE(ctxt, xoff) \
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
648 ctxt->index_mapping[xoff] = -1
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
649 #define NOTE_INSERT(ctxt, yoff) \
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
650 ctxt->index_mapping_reverse[yoff] = -1
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
651 #include "diffseq.h"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
652
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
653 /* Compute the differences between the entries of FILE1 and the entries of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
654 FILE2. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
655 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
656 compute_differences (struct changelog_file *file1, struct changelog_file *file2,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
657 struct differences *result)
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
658 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
659 /* Unlike compute_mapping, which mostly ignores the order of the entries and
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
660 therefore works well when some entries are permuted, here we use the order.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
661 I think this is needed in order to distinguish changes from
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
662 additions+removals; I don't know how to say what is a "change" if the
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
663 files are considered as unordered sets of entries. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
664 struct context ctxt;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
665 size_t n1 = file1->num_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
666 size_t n2 = file2->num_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
667 ssize_t i;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
668 ssize_t j;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
669 gl_list_t /* <struct edit *> */ edits;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
670
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
671 ctxt.xvec = file1->entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
672 ctxt.yvec = file2->entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
673 ctxt.index_mapping = XNMALLOC (n1, ssize_t);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
674 for (i = 0; i < n1; i++)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
675 ctxt.index_mapping[i] = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
676 ctxt.index_mapping_reverse = XNMALLOC (n2, ssize_t);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
677 for (j = 0; j < n2; j++)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
678 ctxt.index_mapping_reverse[j] = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
679 ctxt.fdiag = XNMALLOC (2 * (n1 + n2 + 3), ssize_t) + n2 + 1;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
680 ctxt.bdiag = ctxt.fdiag + n1 + n2 + 3;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
681
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
682 /* Store in ctxt.index_mapping and ctxt.index_mapping_reverse a -1 for
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
683 each removed or added entry. */
17630
d09167851e07 diffseq: remove TOO_EXPENSIVE heuristic
Paul Eggert <eggert@cs.ucla.edu>
parents: 16708
diff changeset
684 compareseq (0, n1, 0, n2, &ctxt);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
685
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
686 /* Complete the index_mapping and index_mapping_reverse arrays. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
687 i = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
688 j = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
689 while (i < n1 || j < n2)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
690 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
691 while (i < n1 && ctxt.index_mapping[i] < 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
692 i++;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
693 while (j < n2 && ctxt.index_mapping_reverse[j] < 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
694 j++;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
695 ASSERT ((i < n1) == (j < n2));
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
696 if (i == n1 && j == n2)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
697 break;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
698 ctxt.index_mapping[i] = j;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
699 ctxt.index_mapping_reverse[j] = i;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
700 i++;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
701 j++;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
702 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
703
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
704 /* Create the edits. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
705 edits = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
706 i = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
707 j = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
708 while (i < n1 || j < n2)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
709 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
710 if (i == n1)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
711 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
712 struct edit *e;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
713 ASSERT (j < n2);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
714 e = XMALLOC (struct edit);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
715 e->type = ADDITION;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
716 e->j1 = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
717 e->j2 = n2 - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
718 gl_list_add_last (edits, e);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
719 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
720 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
721 if (j == n2)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
722 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
723 struct edit *e;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
724 ASSERT (i < n1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
725 e = XMALLOC (struct edit);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
726 e->type = REMOVAL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
727 e->i1 = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
728 e->i2 = n1 - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
729 gl_list_add_last (edits, e);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
730 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
731 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
732 if (ctxt.index_mapping[i] >= 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
733 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
734 if (ctxt.index_mapping_reverse[j] >= 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
735 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
736 ASSERT (ctxt.index_mapping[i] == j);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
737 ASSERT (ctxt.index_mapping_reverse[j] == i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
738 i++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
739 j++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
740 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
741 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
742 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
743 struct edit *e;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
744 ASSERT (ctxt.index_mapping_reverse[j] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
745 e = XMALLOC (struct edit);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
746 e->type = ADDITION;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
747 e->j1 = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
748 do
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
749 j++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
750 while (j < n2 && ctxt.index_mapping_reverse[j] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
751 e->j2 = j - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
752 gl_list_add_last (edits, e);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
753 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
754 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
755 else
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
756 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
757 if (ctxt.index_mapping_reverse[j] >= 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
758 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
759 struct edit *e;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
760 ASSERT (ctxt.index_mapping[i] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
761 e = XMALLOC (struct edit);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
762 e->type = REMOVAL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
763 e->i1 = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
764 do
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
765 i++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
766 while (i < n1 && ctxt.index_mapping[i] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
767 e->i2 = i - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
768 gl_list_add_last (edits, e);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
769 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
770 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
771 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
772 struct edit *e;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
773 ASSERT (ctxt.index_mapping[i] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
774 ASSERT (ctxt.index_mapping_reverse[j] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
775 e = XMALLOC (struct edit);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
776 e->type = CHANGE;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
777 e->i1 = i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
778 do
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
779 i++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
780 while (i < n1 && ctxt.index_mapping[i] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
781 e->i2 = i - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
782 e->j1 = j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
783 do
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
784 j++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
785 while (j < n2 && ctxt.index_mapping_reverse[j] < 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
786 e->j2 = j - 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
787 gl_list_add_last (edits, e);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
788 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
789 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
790 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
791
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
792 result->index_mapping = ctxt.index_mapping;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
793 result->index_mapping_reverse = ctxt.index_mapping_reverse;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
794 result->num_edits = gl_list_size (edits);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
795 result->edits = XNMALLOC (result->num_edits, struct edit *);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
796 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
797 size_t index = 0;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
798 gl_list_iterator_t iter = gl_list_iterator (edits);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
799 const void *elt;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
800 gl_list_node_t node;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
801 while (gl_list_iterator_next (&iter, &elt, &node))
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
802 result->edits[index++] = (struct edit *) elt;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
803 gl_list_iterator_free (&iter);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
804 ASSERT (index == result->num_edits);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
805 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
806 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
807
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
808 /* An empty entry. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
809 static struct entry empty_entry = { NULL, 0 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
810
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
811 /* Return the end a paragraph.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
812 ENTRY is an entry.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
813 OFFSET is an offset into the entry, OFFSET <= ENTRY->length.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
814 Return the offset of the end of paragraph, as an offset <= ENTRY->length;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
815 it is the start of a blank line or the end of the entry. */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
816 static size_t
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
817 find_paragraph_end (const struct entry *entry, size_t offset)
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
818 {
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
819 const char *string = entry->string;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
820 size_t length = entry->length;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
821
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
822 for (;;)
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
823 {
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
824 const char *nl = memchr (string + offset, '\n', length - offset);
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
825 if (nl == NULL)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
826 return length;
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
827 offset = (nl - string) + 1;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
828 if (offset < length && string[offset] == '\n')
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
829 return offset;
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
830 }
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
831 }
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
832
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
833 /* Split a merged entry.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
834 Given an old entry of the form
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
835 TITLE
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
836 BODY
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
837 and a new entry of the form
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
838 TITLE
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
839 BODY1
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
840 BODY'
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
841 where the two titles are the same and BODY and BODY' are very similar,
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
842 this computes two new entries
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
843 TITLE
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
844 BODY1
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
845 and
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
846 TITLE
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
847 BODY'
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
848 and returns true.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
849 If the entries don't have this form, it returns false. */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
850 static bool
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
851 try_split_merged_entry (const struct entry *old_entry,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
852 const struct entry *new_entry,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
853 struct entry *new_split[2])
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
854 {
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
855 size_t old_title_len = find_paragraph_end (old_entry, 0);
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
856 size_t new_title_len = find_paragraph_end (new_entry, 0);
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
857 struct entry old_body;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
858 struct entry new_body;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
859 size_t best_split_offset;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
860 double best_similarity;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
861 size_t split_offset;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
862
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
863 /* Same title? */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
864 if (!(old_title_len == new_title_len
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
865 && memcmp (old_entry->string, new_entry->string, old_title_len) == 0))
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
866 return false;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
867
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
868 old_body.string = old_entry->string + old_title_len;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
869 old_body.length = old_entry->length - old_title_len;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
870
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
871 /* Determine where to split the new entry.
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
872 This is done by maximizing the similarity between BODY and BODY'. */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
873 best_split_offset = split_offset = new_title_len;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
874 best_similarity = 0.0;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
875 for (;;)
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
876 {
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
877 double similarity;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
878
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
879 new_body.string = new_entry->string + split_offset;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
880 new_body.length = new_entry->length - split_offset;
11704
d8024cba4b63 Speed up approximate search for matching ChangeLog entries.
Bruno Haible <bruno@clisp.org>
parents: 11703
diff changeset
881 similarity =
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
882 entry_fstrcmp (&old_body, &new_body, best_similarity);
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
883 if (similarity > best_similarity)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
884 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
885 best_split_offset = split_offset;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
886 best_similarity = similarity;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
887 }
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
888 if (best_similarity == 1.0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
889 /* It cannot get better. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
890 break;
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
891
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
892 if (split_offset < new_entry->length)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
893 split_offset = find_paragraph_end (new_entry, split_offset + 1);
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
894 else
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
895 break;
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
896 }
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
897
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
898 /* BODY' should not be empty. */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
899 if (best_split_offset == new_entry->length)
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
900 return false;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
901 ASSERT (new_entry->string[best_split_offset] == '\n');
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
902
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
903 /* A certain similarity between BODY and BODY' is required. */
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
904 if (best_similarity < FSTRCMP_STRICTER_THRESHOLD)
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
905 return false;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
906
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
907 new_split[0] = entry_create (new_entry->string, best_split_offset + 1);
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
908
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
909 {
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
910 size_t len1 = new_title_len;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
911 size_t len2 = new_entry->length - best_split_offset;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
912 char *combined = XNMALLOC (len1 + len2, char);
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
913 memcpy (combined, new_entry->string, len1);
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
914 memcpy (combined + len1, new_entry->string + best_split_offset, len2);
9713
9bd638fc6986 Speed up by 25%.
Bruno Haible <bruno@clisp.org>
parents: 9712
diff changeset
915 new_split[1] = entry_create (combined, len1 + len2);
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
916 }
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
917
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
918 return true;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
919 }
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
920
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
921 /* Write the contents of an entry to the output stream FP. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
922 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
923 entry_write (FILE *fp, struct entry *entry)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
924 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
925 if (entry->length > 0)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
926 fwrite (entry->string, 1, entry->length, fp);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
927 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
928
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
929 /* This structure represents a conflict.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
930 A conflict can occur for various reasons. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
931 struct conflict
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
932 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
933 /* Parts from the ancestor file. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
934 size_t num_old_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
935 struct entry **old_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
936 /* Parts of the modified file. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
937 size_t num_modified_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
938 struct entry **modified_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
939 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
940
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
941 /* Write a conflict to the output stream FP, including markers. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
942 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
943 conflict_write (FILE *fp, struct conflict *c)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
944 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
945 size_t i;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
946
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
947 /* Use the same syntax as git's default merge driver.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
948 Don't indent the contents of the entries (with things like ">" or "-"),
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
949 otherwise the user needs more textual editing to resolve the conflict. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
950 fputs ("<<<<<<<\n", fp);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
951 for (i = 0; i < c->num_old_entries; i++)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
952 entry_write (fp, c->old_entries[i]);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
953 fputs ("=======\n", fp);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
954 for (i = 0; i < c->num_modified_entries; i++)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
955 entry_write (fp, c->modified_entries[i]);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
956 fputs (">>>>>>>\n", fp);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
957 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
958
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
959 /* Long options. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
960 static const struct option long_options[] =
10092
ae7bf97ee30c Remove trailing spaces.
Bruno Haible <bruno@clisp.org>
parents: 9909
diff changeset
961 {
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
962 { "help", no_argument, NULL, 'h' },
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
963 { "split-merged-entry", no_argument, NULL, CHAR_MAX + 1 },
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
964 { "version", no_argument, NULL, 'V' },
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
965 { NULL, 0, NULL, 0 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
966 };
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
967
16358
a712776b11ce maint: spelling fixes
Paul Eggert <eggert@cs.ucla.edu>
parents: 16234
diff changeset
968 /* Print a usage message and exit. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
969 static void
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
970 usage (int status)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
971 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
972 if (status != EXIT_SUCCESS)
16234
f9b906545e2f Use ', not `, for quoting output.
Paul Eggert <eggert@cs.ucla.edu>
parents: 13551
diff changeset
973 fprintf (stderr, "Try '%s --help' for more information.\n",
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
974 program_name);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
975 else
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
976 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
977 printf ("Usage: %s [OPTION] O-FILE-NAME A-FILE-NAME B-FILE-NAME\n",
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
978 program_name);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
979 printf ("\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
980 printf ("Merges independent modifications of a ChangeLog style file.\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
981 printf ("O-FILE-NAME names the original file, the ancestor of the two others.\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
982 printf ("A-FILE-NAME names the publicly modified file.\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
983 printf ("B-FILE-NAME names the user-modified file.\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
984 printf ("Writes the merged file into A-FILE-NAME.\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
985 printf ("\n");
13364
f07c1f071ff0 git-merge-changelog: Enable --split-merged-entry by default.
Bruno Haible <bruno@clisp.org>
parents: 12445
diff changeset
986 #if 0 /* --split-merged-entry is now on by default. */
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
987 printf ("Operation modifiers:\n");
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
988 printf ("\
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
989 --split-merged-entry Possibly split a merged entry between paragraphs.\n\
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
990 Use this if you have the habit to merge unrelated\n\
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
991 entries into a single one, separated only by a\n\
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
992 newline, just because they happened on the same\n\
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
993 date.\n");
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
994 printf ("\n");
13364
f07c1f071ff0 git-merge-changelog: Enable --split-merged-entry by default.
Bruno Haible <bruno@clisp.org>
parents: 12445
diff changeset
995 #endif
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
996 printf ("Informative output:\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
997 printf (" -h, --help display this help and exit\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
998 printf (" -V, --version output version information and exit\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
999 printf ("\n");
16707
47613935f655 git-merge-changelog: Report bugs to bug-gnulib@gnu.org.
Mark Wielaard <mark@klomp.org>
parents: 16358
diff changeset
1000 fputs ("Report bugs to <bug-gnulib@gnu.org>.\n",
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1001 stdout);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1002 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1003
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1004 exit (status);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1005 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1006
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1007 int
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1008 main (int argc, char *argv[])
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1009 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1010 int optchar;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1011 bool do_help;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1012 bool do_version;
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
1013 bool split_merged_entry;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1014
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1015 /* Set program name for messages. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1016 set_program_name (argv[0]);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1017
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1018 /* Set default values for variables. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1019 do_help = false;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1020 do_version = false;
13364
f07c1f071ff0 git-merge-changelog: Enable --split-merged-entry by default.
Bruno Haible <bruno@clisp.org>
parents: 12445
diff changeset
1021 split_merged_entry = true;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1022
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1023 /* Parse command line options. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1024 while ((optchar = getopt_long (argc, argv, "hV", long_options, NULL)) != EOF)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1025 switch (optchar)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1026 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1027 case '\0': /* Long option. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1028 break;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1029 case 'h':
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1030 do_help = true;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1031 break;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1032 case 'V':
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1033 do_version = true;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1034 break;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1035 case CHAR_MAX + 1: /* --split-merged-entry */
9711
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
1036 break;
4e8a8a9b5391 New option --split-merged-entry.
Bruno Haible <bruno@clisp.org>
parents: 9710
diff changeset
1037 default:
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1038 usage (EXIT_FAILURE);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1039 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1040
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1041 if (do_version)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1042 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1043 /* Version information is requested. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1044 printf ("%s\n", program_name);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1045 printf ("Copyright (C) %s Free Software Foundation, Inc.\n\
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1046 License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n\
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1047 This is free software: you are free to change and redistribute it.\n\
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1048 There is NO WARRANTY, to the extent permitted by law.\n\
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1049 ",
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1050 "2008");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1051 printf ("Written by %s.\n", "Bruno Haible");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1052 exit (EXIT_SUCCESS);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1053 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1054
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1055 if (do_help)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1056 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1057 /* Help is requested. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1058 usage (EXIT_SUCCESS);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1059 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1060
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1061 /* Test argument count. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1062 if (optind + 3 != argc)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1063 error (EXIT_FAILURE, 0, "expected three arguments");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1064
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1065 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1066 const char *ancestor_file_name; /* O-FILE-NAME */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1067 const char *destination_file_name; /* A-FILE-NAME */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1068 bool downstream;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1069 const char *other_file_name; /* B-FILE-NAME */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1070 const char *mainstream_file_name;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1071 const char *modified_file_name;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1072 struct changelog_file ancestor_file;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1073 struct changelog_file mainstream_file;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1074 struct changelog_file modified_file;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1075 /* Mapping from indices in ancestor_file to indices in mainstream_file. */
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
1076 struct entries_mapping mapping;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1077 struct differences diffs;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1078 gl_list_node_t *result_entries_pointers; /* array of pointers into result_entries */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1079 gl_list_t /* <struct entry *> */ result_entries;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1080 gl_list_t /* <struct conflict *> */ result_conflicts;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1081
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1082 ancestor_file_name = argv[optind];
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1083 destination_file_name = argv[optind + 1];
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1084 other_file_name = argv[optind + 2];
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1085
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1086 /* Heuristic to determine whether it's a pull in downstream direction
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1087 (e.g. pull from a centralized server) or a pull in upstream direction
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1088 (e.g. "git stash apply").
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1089
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1090 For ChangeLog this distinction is important. The difference between
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1091 an "upstream" and a "downstream" repository is that more people are
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1092 looking at the "upstream" repository. They want to be informed about
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1093 changes and expect them to be shown at the top of the ChangeLog.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1094 When a user pulls downstream, on the other hand, he has two options:
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1095 a) He gets the change entries from the central repository also at the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1096 top of his ChangeLog, and his own changes come after them.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1097 b) He gets the change entries from the central repository after those
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1098 he has collected for his branch. His own change entries stay at
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1099 the top of the ChangeLog file.
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1100 In the case a) he has to reorder the ChangeLog before he can commit.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1101 No one does that. So most people want b).
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1102 In other words, the order of entries in a ChangeLog should represent
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1103 the order in which they have flown (or will flow) into the *central*
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1104 repository.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1105
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1106 But in git this is fundamentally indistinguishable, because when Linus
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1107 pulls patches from akpm and akpm pulls patches from Linus, it's not
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1108 clear which of the two is more "upstream". Also, when you have many
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1109 branches in a repository and pull from one to another, "git" has no way
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1110 to know which branch is more "upstream" than the other. The git-tag(1)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1111 manual page also says:
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1112 "One important aspect of git is it is distributed, and being
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1113 distributed largely means there is no inherent "upstream" or
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1114 "downstream" in the system."
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1115 Therefore anyone who attempts to produce a ChangeLog from the merge
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1116 history will fail.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1117
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1118 Here we allow the user to specify the pull direction through an
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1119 environment variable (GIT_UPSTREAM or GIT_DOWNSTREAM). If these two
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1120 environment variables are not set, we assume a "simple single user"
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1121 usage pattern: He manages local changes through stashes and uses
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1122 "git pull" only to pull downstream.
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1123
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1124 How to distinguish these situation? There are several hints:
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1125 - During a "git stash apply", GIT_REFLOG_ACTION is not set. During
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1126 a "git pull", it is set to 'pull '. During a "git pull --rebase",
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1127 it is set to 'pull --rebase'. During a "git cherry-pick", it is
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1128 set to 'cherry-pick'.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1129 - During a "git stash apply", there is an environment variable of
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1130 the form GITHEAD_<40_hex_digits>='Stashed changes'. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1131 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1132 const char *var;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1133
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1134 var = getenv ("GIT_DOWNSTREAM");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1135 if (var != NULL && var[0] != '\0')
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1136 downstream = true;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1137 else
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1138 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1139 var = getenv ("GIT_UPSTREAM");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1140 if (var != NULL && var[0] != '\0')
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1141 downstream = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1142 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1143 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1144 var = getenv ("GIT_REFLOG_ACTION");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1145 #if 0 /* Debugging code */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1146 printf ("GIT_REFLOG_ACTION=|%s|\n", var);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1147 #endif
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1148 if (var != NULL
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1149 && ((strncmp (var, "pull", 4) == 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1150 && c_strstr (var, " --rebase") == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1151 || strncmp (var, "merge origin", 12) == 0))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1152 downstream = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1153 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1154 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1155 /* "git stash apply", "git rebase", "git cherry-pick" and
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1156 similar. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1157 downstream = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1158 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1159 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1160 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1161 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1162
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1163 #if 0 /* Debugging code */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1164 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1165 char buf[1000];
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1166 printf ("First line of %%A:\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1167 sprintf (buf, "head -1 %s", destination_file_name); system (buf);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1168 printf ("First line of %%B:\n");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1169 sprintf (buf, "head -1 %s", other_file_name); system (buf);
9710
b2e9096015d9 Support the "git pull --rebase" situation.
Bruno Haible <bruno@clisp.org>
parents: 9693
diff changeset
1170 printf ("Guessing calling convention: %s\n",
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1171 downstream
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1172 ? "%A = modified by user, %B = upstream"
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1173 : "%A = upstream, %B = modified by user");
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1174 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1175 #endif
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1176
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1177 if (downstream)
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1178 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1179 mainstream_file_name = other_file_name;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1180 modified_file_name = destination_file_name;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1181 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1182 else
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1183 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1184 mainstream_file_name = destination_file_name;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1185 modified_file_name = other_file_name;
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1186 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1187
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1188 /* Read the three files into memory. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1189 read_changelog_file (ancestor_file_name, &ancestor_file);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1190 read_changelog_file (mainstream_file_name, &mainstream_file);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1191 read_changelog_file (modified_file_name, &modified_file);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1192
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1193 /* Compute correspondence between the entries of ancestor_file and of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1194 mainstream_file. */
11706
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
1195 compute_mapping (&ancestor_file, &mainstream_file, false, &mapping);
de9937c296ee Speedup git-merge-changelog for git cherry-pick.
Bruno Haible <bruno@clisp.org>
parents: 11705
diff changeset
1196 (void) entries_mapping_reverse_get; /* avoid gcc "defined but not" warning */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1197
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1198 /* Compute differences between the entries of ancestor_file and of
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1199 modified_file. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1200 compute_differences (&ancestor_file, &modified_file, &diffs);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1201
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1202 /* Compute the result. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1203 result_entries_pointers =
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1204 XNMALLOC (mainstream_file.num_entries, gl_list_node_t);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1205 result_entries =
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1206 gl_list_create_empty (GL_LINKED_LIST, entry_equals, entry_hashcode,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1207 NULL, true);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1208 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1209 size_t k;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1210 for (k = 0; k < mainstream_file.num_entries; k++)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1211 result_entries_pointers[k] =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1212 gl_list_add_last (result_entries, mainstream_file.entries[k]);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1213 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1214 result_conflicts =
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1215 gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1216 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1217 size_t e;
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1218 for (e = 0; e < diffs.num_edits; e++)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1219 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1220 struct edit *edit = diffs.edits[e];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1221 switch (edit->type)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1222 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1223 case ADDITION:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1224 if (edit->j1 == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1225 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1226 /* An addition to the top of modified_file.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1227 Apply it to the top of mainstream_file. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1228 ssize_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1229 for (j = edit->j2; j >= edit->j1; j--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1230 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1231 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1232 gl_list_add_first (result_entries, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1233 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1234 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1235 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1236 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1237 ssize_t i_before;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1238 ssize_t i_after;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1239 ssize_t k_before;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1240 ssize_t k_after;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1241 i_before = diffs.index_mapping_reverse[edit->j1 - 1];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1242 ASSERT (i_before >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1243 i_after = (edit->j2 + 1 == modified_file.num_entries
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1244 ? ancestor_file.num_entries
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1245 : diffs.index_mapping_reverse[edit->j2 + 1]);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1246 ASSERT (i_after >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1247 ASSERT (i_after == i_before + 1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1248 /* An addition between ancestor_file.entries[i_before] and
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1249 ancestor_file.entries[i_after]. See whether these two
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1250 entries still exist in mainstream_file and are still
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1251 consecutive. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1252 k_before = entries_mapping_get (&mapping, i_before);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1253 k_after = (i_after == ancestor_file.num_entries
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1254 ? mainstream_file.num_entries
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1255 : entries_mapping_get (&mapping, i_after));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1256 if (k_before >= 0 && k_after >= 0 && k_after == k_before + 1)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1257 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1258 /* Yes, the entry before and after are still neighbours
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1259 in mainstream_file. Apply the addition between
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1260 them. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1261 if (k_after == mainstream_file.num_entries)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1262 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1263 size_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1264 for (j = edit->j1; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1265 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1266 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1267 gl_list_add_last (result_entries, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1268 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1269 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1270 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1271 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1272 gl_list_node_t node_k_after = result_entries_pointers[k_after];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1273 size_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1274 for (j = edit->j1; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1275 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1276 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1277 gl_list_add_before (result_entries, node_k_after, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1278 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1279 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1280 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1281 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1282 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1283 /* It's not clear where the additions should be applied.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1284 Let the user decide. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1285 struct conflict *c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1286 size_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1287 c->num_old_entries = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1288 c->old_entries = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1289 c->num_modified_entries = edit->j2 - edit->j1 + 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1290 c->modified_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1291 XNMALLOC (c->num_modified_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1292 for (j = edit->j1; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1293 c->modified_entries[j - edit->j1] = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1294 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1295 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1296 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1297 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1298 case REMOVAL:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1299 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1300 /* Apply the removals one by one. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1301 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1302 for (i = edit->i1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1303 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1304 struct entry *removed_entry = ancestor_file.entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1305 ssize_t k = entries_mapping_get (&mapping, i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1306 if (k >= 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1307 && entry_equals (removed_entry,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1308 mainstream_file.entries[k]))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1309 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1310 /* The entry to be removed still exists in
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1311 mainstream_file. Remove it. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1312 gl_list_node_set_value (result_entries,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1313 result_entries_pointers[k],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1314 &empty_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1315 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1316 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1317 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1318 /* The entry to be removed was already removed or was
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1319 modified. This is a conflict. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1320 struct conflict *c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1321 c->num_old_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1322 c->old_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1323 XNMALLOC (c->num_old_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1324 c->old_entries[0] = removed_entry;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1325 c->num_modified_entries = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1326 c->modified_entries = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1327 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1328 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1329 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1330 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1331 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1332 case CHANGE:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1333 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1334 bool done = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1335 /* When the user usually merges entries from the same day,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1336 and this edit is at the top of the file: */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1337 if (split_merged_entry && edit->j1 == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1338 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1339 /* Test whether the change is "simple merged", i.e. whether
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1340 it consists of additions, followed by an augmentation of
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1341 the first changed entry, followed by small changes of the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1342 remaining entries:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1343 entry_1
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1344 entry_2
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1345 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1346 entry_n
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1347 are mapped to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1348 added_entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1349 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1350 added_entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1351 augmented_entry_1
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1352 modified_entry_2
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1353 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1354 modified_entry_n. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1355 if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1356 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1357 struct entry *split[2];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1358 bool simple_merged =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1359 try_split_merged_entry (ancestor_file.entries[edit->i1],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1360 modified_file.entries[edit->i1 + edit->j2 - edit->i2],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1361 split);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1362 if (simple_merged)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1363 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1364 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1365 for (i = edit->i1 + 1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1366 if (entry_fstrcmp (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1367 modified_file.entries[i + edit->j2 - edit->i2],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1368 FSTRCMP_THRESHOLD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1369 < FSTRCMP_THRESHOLD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1370 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1371 simple_merged = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1372 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1373 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1374 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1375 if (simple_merged)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1376 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1377 /* Apply the additions at the top of modified_file.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1378 Apply each of the single-entry changes
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1379 separately. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1380 size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1381 size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1382 ssize_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1383 /* First part of the split modified_file.entries[edit->j2 - edit->i2 + edit->i1]: */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1384 gl_list_add_first (result_entries, split[0]);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1385 /* The additions. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1386 for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1387 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1388 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1389 gl_list_add_first (result_entries, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1390 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1391 /* Now the single-entry changes. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1392 for (j = edit->j1 + num_added; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1393 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1394 struct entry *changed_entry =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1395 (j == edit->j1 + num_added
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1396 ? split[1]
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1397 : modified_file.entries[j]);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1398 size_t i = j + edit->i2 - edit->j2;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1399 ssize_t k = entries_mapping_get (&mapping, i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1400 if (k >= 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1401 && entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1402 mainstream_file.entries[k]))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1403 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1404 gl_list_node_set_value (result_entries,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1405 result_entries_pointers[k],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1406 changed_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1407 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1408 else if (!entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1409 changed_entry))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1410 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1411 struct conflict *c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1412 c->num_old_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1413 c->old_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1414 XNMALLOC (c->num_old_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1415 c->old_entries[0] = ancestor_file.entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1416 c->num_modified_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1417 c->modified_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1418 XNMALLOC (c->num_modified_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1419 c->modified_entries[0] = changed_entry;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1420 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1421 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1422 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1423 done = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1424 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1425 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1426 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1427 if (!done)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1428 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1429 bool simple;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1430 /* Test whether the change is "simple", i.e. whether it
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1431 consists of small changes to the old ChangeLog entries
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1432 and additions before them:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1433 entry_1
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1434 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1435 entry_n
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1436 are mapped to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1437 added_entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1438 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1439 added_entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1440 modified_entry_1
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1441 ...
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1442 modified_entry_n. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1443 if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1444 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1445 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1446 simple = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1447 for (i = edit->i1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1448 if (entry_fstrcmp (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1449 modified_file.entries[i + edit->j2 - edit->i2],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1450 FSTRCMP_THRESHOLD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1451 < FSTRCMP_THRESHOLD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1452 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1453 simple = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1454 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1455 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1456 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1457 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1458 simple = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1459 if (simple)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1460 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1461 /* Apply the additions and each of the single-entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1462 changes separately. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1463 size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1464 size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1465 if (edit->j1 == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1466 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1467 /* A simple change at the top of modified_file.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1468 Apply it to the top of mainstream_file. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1469 ssize_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1470 for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1471 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1472 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1473 gl_list_add_first (result_entries, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1474 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1475 for (j = edit->j1 + num_added; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1476 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1477 struct entry *changed_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1478 size_t i = j + edit->i2 - edit->j2;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1479 ssize_t k = entries_mapping_get (&mapping, i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1480 if (k >= 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1481 && entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1482 mainstream_file.entries[k]))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1483 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1484 gl_list_node_set_value (result_entries,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1485 result_entries_pointers[k],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1486 changed_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1487 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1488 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1489 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1490 struct conflict *c;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1491 ASSERT (!entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1492 changed_entry));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1493 c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1494 c->num_old_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1495 c->old_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1496 XNMALLOC (c->num_old_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1497 c->old_entries[0] = ancestor_file.entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1498 c->num_modified_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1499 c->modified_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1500 XNMALLOC (c->num_modified_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1501 c->modified_entries[0] = changed_entry;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1502 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1503 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1504 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1505 done = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1506 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1507 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1508 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1509 ssize_t i_before;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1510 ssize_t k_before;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1511 bool linear;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1512 i_before = diffs.index_mapping_reverse[edit->j1 - 1];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1513 ASSERT (i_before >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1514 /* A simple change after ancestor_file.entries[i_before].
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1515 See whether this entry and the following num_changed
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1516 entries still exist in mainstream_file and are still
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1517 consecutive. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1518 k_before = entries_mapping_get (&mapping, i_before);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1519 linear = (k_before >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1520 if (linear)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1521 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1522 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1523 for (i = i_before + 1; i <= i_before + num_changed; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1524 if (entries_mapping_get (&mapping, i) != k_before + (i - i_before))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1525 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1526 linear = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1527 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1528 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1529 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1530 if (linear)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1531 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1532 gl_list_node_t node_for_insert =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1533 result_entries_pointers[k_before + 1];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1534 ssize_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1535 for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1536 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1537 struct entry *added_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1538 gl_list_add_before (result_entries, node_for_insert, added_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1539 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1540 for (j = edit->j1 + num_added; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1541 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1542 struct entry *changed_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1543 size_t i = j + edit->i2 - edit->j2;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1544 ssize_t k = entries_mapping_get (&mapping, i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1545 ASSERT (k >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1546 if (entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1547 mainstream_file.entries[k]))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1548 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1549 gl_list_node_set_value (result_entries,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1550 result_entries_pointers[k],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1551 changed_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1552 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1553 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1554 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1555 struct conflict *c;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1556 ASSERT (!entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1557 changed_entry));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1558 c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1559 c->num_old_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1560 c->old_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1561 XNMALLOC (c->num_old_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1562 c->old_entries[0] = ancestor_file.entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1563 c->num_modified_entries = 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1564 c->modified_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1565 XNMALLOC (c->num_modified_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1566 c->modified_entries[0] = changed_entry;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1567 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1568 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1569 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1570 done = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1571 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1572 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1573 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1574 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1575 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1576 /* A big change.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1577 See whether the num_changed entries still exist
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1578 unchanged in mainstream_file and are still
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1579 consecutive. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1580 ssize_t i_first;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1581 ssize_t k_first;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1582 bool linear_unchanged;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1583 i_first = edit->i1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1584 k_first = entries_mapping_get (&mapping, i_first);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1585 linear_unchanged =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1586 (k_first >= 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1587 && entry_equals (ancestor_file.entries[i_first],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1588 mainstream_file.entries[k_first]));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1589 if (linear_unchanged)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1590 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1591 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1592 for (i = i_first + 1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1593 if (!(entries_mapping_get (&mapping, i) == k_first + (i - i_first)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1594 && entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1595 mainstream_file.entries[entries_mapping_get (&mapping, i)])))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1596 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1597 linear_unchanged = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1598 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1599 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1600 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1601 if (linear_unchanged)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1602 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1603 gl_list_node_t node_for_insert =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1604 result_entries_pointers[k_first];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1605 ssize_t j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1606 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1607 for (j = edit->j2; j >= edit->j1; j--)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1608 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1609 struct entry *new_entry = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1610 gl_list_add_before (result_entries, node_for_insert, new_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1611 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1612 for (i = edit->i1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1613 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1614 ssize_t k = entries_mapping_get (&mapping, i);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1615 ASSERT (k >= 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1616 ASSERT (entry_equals (ancestor_file.entries[i],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1617 mainstream_file.entries[k]));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1618 gl_list_node_set_value (result_entries,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1619 result_entries_pointers[k],
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1620 &empty_entry);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1621 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1622 done = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1623 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1624 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1625 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1626 if (!done)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1627 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1628 struct conflict *c = XMALLOC (struct conflict);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1629 size_t i, j;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1630 c->num_old_entries = edit->i2 - edit->i1 + 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1631 c->old_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1632 XNMALLOC (c->num_old_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1633 for (i = edit->i1; i <= edit->i2; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1634 c->old_entries[i - edit->i1] = ancestor_file.entries[i];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1635 c->num_modified_entries = edit->j2 - edit->j1 + 1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1636 c->modified_entries =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1637 XNMALLOC (c->num_modified_entries, struct entry *);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1638 for (j = edit->j1; j <= edit->j2; j++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1639 c->modified_entries[j - edit->j1] = modified_file.entries[j];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1640 gl_list_add_last (result_conflicts, c);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1641 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1642 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1643 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1644 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1645 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1646 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1647
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1648 /* Output the result. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1649 {
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1650 FILE *fp = fopen (destination_file_name, "w");
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1651 if (fp == NULL)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1652 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1653 fprintf (stderr, "could not write file '%s'\n", destination_file_name);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1654 exit (EXIT_FAILURE);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1655 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1656
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1657 /* Output the conflicts at the top. */
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1658 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1659 size_t n = gl_list_size (result_conflicts);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1660 size_t i;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1661 for (i = 0; i < n; i++)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1662 conflict_write (fp, (struct conflict *) gl_list_get_at (result_conflicts, i));
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1663 }
9714
5122118a6300 Speed up by 10%.
Bruno Haible <bruno@clisp.org>
parents: 9713
diff changeset
1664 /* Output the modified and unmodified entries, in order. */
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1665 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1666 gl_list_iterator_t iter = gl_list_iterator (result_entries);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1667 const void *elt;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1668 gl_list_node_t node;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1669 while (gl_list_iterator_next (&iter, &elt, &node))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1670 entry_write (fp, (struct entry *) elt);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1671 gl_list_iterator_free (&iter);
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1672 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1673
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1674 if (fwriteerror (fp))
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1675 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1676 fprintf (stderr, "error writing to file '%s'\n", destination_file_name);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1677 exit (EXIT_FAILURE);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 11707
diff changeset
1678 }
9690
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1679 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1680
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1681 exit (gl_list_size (result_conflicts) > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1682 }
521de8c5a745 New module 'git-merge-changelog'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1683 }