2006-07-31 02:25:18 +08:00
|
|
|
#ifndef UNPACK_TREES_H
|
|
|
|
#define UNPACK_TREES_H
|
|
|
|
|
2018-08-16 01:54:05 +08:00
|
|
|
#include "cache.h"
|
2018-05-21 22:54:28 +08:00
|
|
|
#include "argv-array.h"
|
2018-08-16 01:54:05 +08:00
|
|
|
#include "string-list.h"
|
|
|
|
#include "tree-walk.h"
|
2010-11-16 03:52:19 +08:00
|
|
|
|
2008-03-14 13:07:18 +08:00
|
|
|
#define MAX_UNPACK_TREES 8
|
|
|
|
|
2018-08-16 01:54:05 +08:00
|
|
|
struct cache_entry;
|
2006-07-31 02:25:18 +08:00
|
|
|
struct unpack_trees_options;
|
2009-08-20 21:47:08 +08:00
|
|
|
struct exclude_list;
|
2006-07-31 02:25:18 +08:00
|
|
|
|
2013-06-02 23:46:56 +08:00
|
|
|
typedef int (*merge_fn_t)(const struct cache_entry * const *src,
|
2008-03-07 10:12:28 +08:00
|
|
|
struct unpack_trees_options *options);
|
2006-07-31 02:25:18 +08:00
|
|
|
|
2010-08-11 16:38:04 +08:00
|
|
|
enum unpack_trees_error_types {
|
|
|
|
ERROR_WOULD_OVERWRITE = 0,
|
|
|
|
ERROR_NOT_UPTODATE_FILE,
|
|
|
|
ERROR_NOT_UPTODATE_DIR,
|
2010-08-11 16:38:06 +08:00
|
|
|
ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN,
|
|
|
|
ERROR_WOULD_LOSE_UNTRACKED_REMOVED,
|
2010-08-11 16:38:04 +08:00
|
|
|
ERROR_BIND_OVERLAP,
|
|
|
|
ERROR_SPARSE_NOT_UPTODATE_FILE,
|
2010-08-11 16:38:06 +08:00
|
|
|
ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN,
|
|
|
|
ERROR_WOULD_LOSE_ORPHANED_REMOVED,
|
2017-03-15 05:46:39 +08:00
|
|
|
ERROR_WOULD_LOSE_SUBMODULE,
|
2010-08-11 16:38:04 +08:00
|
|
|
NB_UNPACK_TREES_ERROR_TYPES
|
2008-05-18 03:03:49 +08:00
|
|
|
};
|
|
|
|
|
2010-09-02 19:57:33 +08:00
|
|
|
/*
|
|
|
|
* Sets the list of user-friendly error messages to be used by the
|
2010-09-03 00:08:15 +08:00
|
|
|
* command "cmd" (either merge or checkout), and show_all_errors to 1.
|
2010-09-02 19:57:33 +08:00
|
|
|
*/
|
2010-09-02 19:57:34 +08:00
|
|
|
void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
|
|
|
|
const char *cmd);
|
2010-09-02 19:57:33 +08:00
|
|
|
|
2018-05-21 22:54:28 +08:00
|
|
|
/*
|
|
|
|
* Frees resources allocated by setup_unpack_trees_porcelain().
|
|
|
|
*/
|
|
|
|
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts);
|
|
|
|
|
2006-07-31 02:25:18 +08:00
|
|
|
struct unpack_trees_options {
|
2009-06-26 13:14:10 +08:00
|
|
|
unsigned int reset,
|
|
|
|
merge,
|
|
|
|
update,
|
2018-08-18 02:00:39 +08:00
|
|
|
clone,
|
2009-06-26 13:14:10 +08:00
|
|
|
index_only,
|
|
|
|
nontrivial_merge,
|
|
|
|
trivial_merges_only,
|
|
|
|
verbose_update,
|
|
|
|
aggressive,
|
|
|
|
skip_unmerged,
|
|
|
|
initial_checkout,
|
|
|
|
diff_index_cached,
|
2009-09-14 17:22:00 +08:00
|
|
|
debug_unpack,
|
2009-08-20 21:47:08 +08:00
|
|
|
skip_sparse_checkout,
|
2010-08-11 16:38:07 +08:00
|
|
|
gently,
|
2011-06-01 01:06:44 +08:00
|
|
|
exiting_early,
|
2011-05-26 04:07:51 +08:00
|
|
|
show_all_errors,
|
|
|
|
dry_run;
|
2006-07-31 02:25:18 +08:00
|
|
|
const char *prefix;
|
unpack-trees.c: prepare for looking ahead in the index
This prepares but does not yet implement a look-ahead in the index entries
when traverse-trees.c decides to give us tree entries in an order that
does not match what is in the index.
A case where a look-ahead in the index is necessary happens when merging
branch B into branch A while the index matches the current branch A, using
a tree O as their common ancestor, and these three trees looks like this:
O A B
t t
t-i t-i t-i
t-j t-j
t/1
t/2
The traverse_trees() function gets "t", "t-i" and "t" from trees O, A and
B first, and notices that A may have a matching "t" behind "t-i" and "t-j"
(indeed it does), and tells A to give that entry instead. After unpacking
blob "t" from tree B (as it hasn't changed since O in B and A removed it,
it will result in its removal), it descends into directory "t/".
The side that walked index in parallel to the tree traversal used to be
implemented with one pointer, o->pos, that points at the next index entry
to be processed. When this happens, the pointer o->pos still points at
"t-i" that is the first entry. We should be able to skip "t-i" and "t-j"
and locate "t/1" from the index while the recursive invocation of
traverse_trees() walks and match entries found there, and later come back
to process "t-i".
While that look-ahead is not implemented yet, this adds a flag bit,
CE_UNPACKED, to mark the entries in the index that has already been
processed. o->pos pointer has been renamed to o->cache_bottom and it
points at the first entry that may still need to be processed.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-08 06:59:54 +08:00
|
|
|
int cache_bottom;
|
2006-12-05 08:00:46 +08:00
|
|
|
struct dir_struct *dir;
|
2011-08-30 03:31:06 +08:00
|
|
|
struct pathspec *pathspec;
|
2006-07-31 02:25:18 +08:00
|
|
|
merge_fn_t fn;
|
2010-08-11 16:38:04 +08:00
|
|
|
const char *msgs[NB_UNPACK_TREES_ERROR_TYPES];
|
2018-05-21 22:54:28 +08:00
|
|
|
struct argv_array msgs_to_free;
|
2010-08-11 16:38:07 +08:00
|
|
|
/*
|
|
|
|
* Store error messages in an array, each case
|
|
|
|
* corresponding to a error message type
|
|
|
|
*/
|
2010-11-16 03:52:19 +08:00
|
|
|
struct string_list unpack_rejects[NB_UNPACK_TREES_ERROR_TYPES];
|
2006-07-31 02:25:18 +08:00
|
|
|
|
|
|
|
int head_idx;
|
|
|
|
int merge_size;
|
|
|
|
|
|
|
|
struct cache_entry *df_conflict_entry;
|
Make run_diff_index() use unpack_trees(), not read_tree()
A plain "git commit" would still run lstat() a lot more than necessary,
because wt_status_print() would cause the index to be repeatedly flushed
and re-read by wt_read_cache(), and that would cause the CE_UPTODATE bit
to be lost, resulting in the files in the index being lstat'ed three
times each.
The reason why wt-status.c ended up invalidating and re-reading the
cache multiple times was that it uses "run_diff_index()", which in turn
uses "read_tree()" to populate the index with *both* the old index and
the tree we want to compare against.
So this patch re-writes run_diff_index() to not use read_tree(), but
instead use "unpack_trees()" to diff the index to a tree. That, in
turn, means that we don't need to modify the index itself, which then
means that we don't need to invalidate it and re-read it!
This, together with the lstat() optimizations, means that "git commit"
on the kernel tree really only needs to lstat() the index entries once.
That noticeably cuts down on the cached timings.
Best time before:
[torvalds@woody linux]$ time git commit > /dev/null
real 0m0.399s
user 0m0.232s
sys 0m0.164s
Best time after:
[torvalds@woody linux]$ time git commit > /dev/null
real 0m0.254s
user 0m0.140s
sys 0m0.112s
so it's a noticeable improvement in addition to being a nice conceptual
cleanup (it's really not that pretty that "run_diff_index()" dirties the
index!)
Doing an "strace -c" on it also shows that as it cuts the number of
lstat() calls by two thirds, it goes from being lstat()-limited to being
limited by getdents() (which is the readdir system call):
Before:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
60.69 0.000704 0 69230 31 lstat
23.62 0.000274 0 5522 getdents
8.36 0.000097 0 5508 2638 open
2.59 0.000030 0 2869 close
2.50 0.000029 0 274 write
1.47 0.000017 0 2844 fstat
After:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.17 0.000276 0 5522 getdents
26.51 0.000162 0 23112 31 lstat
19.80 0.000121 0 5503 2638 open
4.91 0.000030 0 2864 close
1.48 0.000020 0 274 write
1.34 0.000018 0 2844 fstat
...
It passes the test-suite for me, but this is another of one of those
really core functions, and certainly pretty subtle, so..
NOTE! The Linux lstat() system call is really quite cheap when everything
is cached, so the fact that this is quite noticeable on Linux is likely to
mean that it is *much* more noticeable on other operating systems. I bet
you'll see a much bigger performance improvement from this on Windows in
particular.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-01-20 09:27:12 +08:00
|
|
|
void *unpack_data;
|
2008-03-07 10:12:28 +08:00
|
|
|
|
|
|
|
struct index_state *dst_index;
|
2008-03-23 00:35:59 +08:00
|
|
|
struct index_state *src_index;
|
2008-03-07 10:12:28 +08:00
|
|
|
struct index_state result;
|
2009-08-20 21:47:08 +08:00
|
|
|
|
|
|
|
struct exclude_list *el; /* for internal use */
|
2006-07-31 02:25:18 +08:00
|
|
|
};
|
|
|
|
|
2018-08-14 00:14:25 +08:00
|
|
|
int unpack_trees(unsigned n, struct tree_desc *t,
|
|
|
|
struct unpack_trees_options *options);
|
2006-07-31 02:25:18 +08:00
|
|
|
|
2018-04-20 01:58:12 +08:00
|
|
|
int verify_uptodate(const struct cache_entry *ce,
|
|
|
|
struct unpack_trees_options *o);
|
|
|
|
|
2013-06-02 23:46:56 +08:00
|
|
|
int threeway_merge(const struct cache_entry * const *stages,
|
|
|
|
struct unpack_trees_options *o);
|
|
|
|
int twoway_merge(const struct cache_entry * const *src,
|
|
|
|
struct unpack_trees_options *o);
|
|
|
|
int bind_merge(const struct cache_entry * const *src,
|
|
|
|
struct unpack_trees_options *o);
|
|
|
|
int oneway_merge(const struct cache_entry * const *src,
|
|
|
|
struct unpack_trees_options *o);
|
2006-07-31 02:26:15 +08:00
|
|
|
|
2006-07-31 02:25:18 +08:00
|
|
|
#endif
|