Commit Graph

310 Commits

Author SHA1 Message Date
Carlos Martín Nieto
9d81509ab1 index: get rid of the locking
We don't support using an index object from multiple threads at the same
time, so the locking doesn't have any effect when following the
rules. If not following the rules, things are going to break down
anyway.
2015-12-28 13:55:44 +00:00
Vicent Marti
ef8b7febc5 index: Also size-hint the hash table
Note that we're not checking whether the resize succeeds; in OOM cases,
we let it run with a "small" vector and hash table and see if by chance
we can grow it dynamically as we insert the new entries. Nothing to
lose really.
2015-12-16 19:36:50 +01:00
Vicent Marti
d7d46cfbfd index: Preallocate the entries vector with size hint 2015-12-16 17:04:08 +01:00
Vicent Marti
0cc20a8c48 index: Adjust namemask & mode when filling 2015-12-16 17:04:08 +01:00
Vicent Marti
879ebab314 merge: Use git_index__fill to populate the index
Instead of calling `git_index_add` in a loop, use the new
`git_index_fill` internal API to fill the index with the initial staged
entries.

The new `fill` helper assumes that all the entries will be unique and
valid, so it can append them at the end of the entries vector and only
sort it once at the end. It performs no validation checks.

This prevents the quadratic behavior caused by having to sort the
entries list once after every insertion.
2015-12-16 12:30:52 +01:00
Carlos Martín Nieto
dc49eb585f Merge pull request #3538 from pks-t/pks/index-memory-leak
index: always queue `remove_entry` for removal
2015-12-10 11:57:44 +01:00
Patrick Steinhardt
b057fdef69 index: always queue remove_entry for removal
When replacing an index with a new one, we need to iterate
through all index entries in order to determine which entries are
equal. When it is not possible to re-use old entries for the new
index, we move it into a list of entries that are to be removed
and thus free'd.

When we encounter a non-zero error code, though, we skip adding
the current index entry to the remove-queue. `INSERT_MAP_EX`,
which is the function last run before adding to the remove-queue,
may return a positive non-zero code that indicates what exactly
happened while inserting the element. In this case we skip adding
the entry to the remove-queue but still continue the current
operation, leading to a leak of the current entry.

Fix this by checking for a negative return value instead of a
non-zero one when we want to add the current index entry to the
remove-queue.
2015-12-08 16:29:08 +01:00
Edward Thomson
626f9e243e index: canonicalize inserted paths safely
When adding to the index, we look to see if a portion of the given
path matches a portion of a path in the index.  If so, we will use
the existing path information.  For example, when adding `foo/bar.c`,
if there is an index entry to `FOO/other` and the filesystem is case
insensitive, then we will put `bar.c` into the existing tree instead
of creating a new one with a different case.

Use `strncmp` to do that instead of `memcmp`.  When we `bsearch`
into the index, we locate the position where the new entry would
go.  The index entry at that position does not necessarily have
a relation to the entry we're adding, so we cannot make assumptions
and use `memcmp`.  Instead, compare them as strings.

When canonicalizing paths, we look for the first index entry that
matches a given substring.
2015-12-03 16:27:15 -05:00
Edward Thomson
25e84f959a checkout: only consider nsecs when built that way
When examining the working directory and determining whether it's
up-to-date, only consider the nanoseconds in the index entry when
built with `GIT_USE_NSEC`.  This prevents us from believing that
the working directory is always dirty when the index was originally
written with a git client that uinderstands nsecs (like git 2.x).
2015-11-23 15:49:54 -05:00
Edward Thomson
5f32c50683 racy: make git_index_read_index handle raciness
Ensure that `git_index_read_index` clears the uptodate bit on
files that it modifies.

Further, do not propagate the cache from an on-disk index into
another on-disk index.  Although this should not be done, as
`git_index_read_index` is used to bring an in-memory index into
another index (that may or may not be on-disk), ensure that we do
not accidentally bring in these bits when misused.
2015-11-16 22:59:02 -05:00
Edward Thomson
27bc41cf17 index: clear uptodate bit on save
The uptodate bit should have a lifecycle of a single read->write
on the index.  Once the index is written, the files within it should
be scanned for racy timestamps against the new index timestamp.
2015-11-16 22:59:01 -05:00
Edward Thomson
d1101263f7 index: don't detect raciness in uptodate entries
Keep track of entries that we believe are up-to-date, because we
added the index entries since the index was loaded.  This prevents
us from unnecessarily examining files that we wrote during the
cleanup of racy entries (when we smudge racily clean files that have
a timestamp newer than or equal to the index's timestamp when we
read it).  Without keeping track of this, we would examine every
file that we just checked out for raciness, since all their timestamps
would be newer than the index's timestamp.
2015-11-16 22:58:58 -05:00
Edward Thomson
cb0ff012d3 racy-git: do a single index->workdir diff
When examining paths that are racily clean, do a single index->workdir
diff over the entirety of the racily clean files, instead of a diff
per file.
2015-11-16 22:58:57 -05:00
Carlos Martín Nieto
75a0ccf52f Merge pull request #3170 from CmdrMoozy/nsec_fix
git_index_entry__init_from_stat: set nsec fields in entry stats
2015-11-12 19:53:09 +01:00
Carlos Martín Nieto
ad8509ef9f index: overwrite the path when inserting conflicts
When we insert a conflict in a case-insensitive index, accept the
new entry's path as the correct case instead of leaving the path we
already had.

This puts `git_index_conflict_add()` on the same level as
`git_index_add()` in this respect.
2015-11-12 12:11:45 +01:00
Carlos Martín Nieto
16604d7469 index: correctly report which conflict stage has a wrong filemode
When we're at offset 'i', we're dealing with the 'i+1' stage, since
conflicts start at 1.
2015-11-12 12:11:45 +01:00
Edward Thomson
0bf77e3283 index: read_index must update hashes 2015-10-30 13:07:51 -04:00
Vicent Marti
1e5e02b4f4 pool: Simplify implementation 2015-10-28 10:13:13 +01:00
Vicent Marti
d307a0134b reuc: Be smarter when inserting new REUC entries
Inserting new REUC entries can quickly become pathological given that
each insert unsorts the REUC vector, and both subsequent lookups *and*
insertions will require sorting it again before being successful.

To avoid this, we're switching to `git_vector_insert_sorted`: this keeps
the REUC vector constantly sorted and lets us use the `on_dup` callback
to skip an extra binary search on each insertion.
2015-10-27 22:44:13 +01:00
Vicent Marti
128e94bbbb index: Remove unneeded consts 2015-10-21 12:04:53 +02:00
Edward Thomson
21515f228b index: also try conflict mode when inserting
When we do not trust the on-disk mode, we use the mode of an existing
index entry.  This allows us to preserve executable bits on platforms
that do not honor them on the filesystem.

If there is no stage 0 index entry, also look at conflicts to attempt
to answer this question:  prefer the data from the 'ours' side, then
the 'theirs' side before falling back to the common ancestor.
2015-09-30 09:06:09 -04:00
Axel Rasmussen
0226f7dd36 diff/index: respect USE_NSEC for racily clean file detection 2015-09-18 23:33:56 -07:00
Axel Rasmussen
e9e6df2c8f cmake: Only provide USE_NSEC if struct stat members are avilable.
This allows us to remove OS checks from source code, instead relying
on CMake to detect whether or not `struct stat` has the nanoseconds
members we rely on.
2015-09-18 23:33:56 -07:00
Axel Rasmussen
e7de893ef8 cmake: add USE_NSEC, and only check nanosec m/ctime if enabled 2015-09-18 23:33:55 -07:00
Carlos Martín Nieto
6d6020defc Merge pull request #3353 from ethomson/wrongcase_add
index: canonicalize directory case when adding
2015-09-08 18:34:51 +02:00
Edward Thomson
2964cbeae1 Merge pull request #3381 from leoyanggit/index_directory_iterator
New feature: add the ablility to iterate through a directory in index
2015-09-08 11:50:08 -04:00
Edward Thomson
a32bc85e84 git_index_add: allow case changing renames
On case insensitive platforms, allow `git_index_add` to provide a new
path for an existing index entry.  Previously, we would maintain the
case in an index entry without the ability to change it (except by
removing an entry and re-adding it.)

Higher-level functions (like `git_index_add_bypath` and
`git_index_add_frombuffers`) continue to keep the old path for easier
usage.
2015-09-08 11:34:00 -04:00
Edward Thomson
280adb3f94 index: canonicalize directory case when adding
On case insensitive systems, when given a user-provided path in the
higher-level index addition functions (eg `git_index_add_bypath` /
`git_index_add_frombuffer`), examine the index to try to match the
given path to an existing directory.

Various mechanisms can cause the on-disk representation of a folder
to not match the representation in HEAD or the index - for example,
a case changing rename of some file `a/file.txt` to `A/file.txt`
will update the paths in the index, but not rename the folder on
disk.

If a user subsequently adds `a/other.txt`, then this should be stored
in the index as `A/other.txt`.
2015-09-08 11:32:40 -04:00
Edward Thomson
9fd4c9c867 Merge pull request #3366 from libgit2/cmn/index-hashmap
Use a hashmap for path-based lookups in the index
2015-09-06 10:50:22 -04:00
Leo Yang
c097f7173d New API: git_index_find_prefix
Find the first index entry matching a prefix.
2015-09-04 12:24:36 -04:00
Carlos Martín Nieto
81b7636757 index: put the icase insert choice in macros
This should let us see more clearly what we're doing and avoid the ugly
'if' we need every time we want to interact with the map.
2015-09-04 13:50:25 +02:00
Edward Thomson
810cabb9df racy-git: TODO to use improved diffing 2015-08-28 18:39:57 -04:00
Edward Thomson
ed1c64464a iterator: use an options struct instead of args 2015-08-28 18:39:47 -04:00
Carlos Martín Nieto
af1d5239a1 index: keep a hash table as well as a vector of entries
The hash table allows quick lookup of specific paths, while we use the
vector for enumeration.
2015-08-14 21:10:12 +02:00
Edward Thomson
ef4857c2b3 errors: tighten up git_error_state OOMs a bit more
When an error state is an OOM, make sure that we treat is specially
and do not try to free it.
2015-08-03 19:44:51 -04:00
Carlos Martín Nieto
ea961abf24 index: stage an unregistered submodule as well
We previously added logic to `_add_bypath()` to update a submodule. Go
further and stage the submodule even if it's not registered to behave
like git.
2015-08-01 20:01:11 +02:00
Carlos Martín Nieto
247d27c2c6 index: allow add_bypath to update submodules
Similarly to how git itself does it, allow the index update operation to
stage a change in a submodule's HEAD.
2015-07-12 12:11:22 +02:00
Carlos Martín Nieto
7497584651 index: check racily clean entries more thoroughly
When an entry has a racy timestamp, we need to check whether the file
itself has changed since we put its entry in the index. Only then do we
smudge the size field to force a check the next time around.
2015-06-22 12:47:30 +02:00
Carlos Martín Nieto
624c949f01 index: make relative comparison use the checksum as well
This is used by the submodule in order to figure out if the index has
changed since it last read it. Using a timestamp is racy, so let's make
it use the checksum, just like we now do for reloading the index itself.
2015-06-20 16:17:28 +02:00
Carlos Martín Nieto
5e947c91d4 index: use the checksum to check whether it's been modified
We currently use a timetamp to check whether an index file has been
modified since we last read it, but this is racy. If two updates happen
in the same second and we read after the first one, we won't detect the
second one.

Instead read the SHA-1 checksum of the file, which are its last 20 bytes which
gives us a sure-fire way to detect whether the file has changed since we
last read it.

As we're now keeping track of it, expose an accessor to this data.
2015-06-19 22:05:08 +02:00
Carlos Martín Nieto
316b820b6f index: zero the size of racily-clean entries
If a file entry has the same timestamp as the index itself, it is
considered racily-clean, as it may have been modified after the index
was written, but during the same second. We take extra steps to check
the contents, but this is just one part of avoiding races.

For files which do have changes but have not been updated in the index,
updating the on-disk index means updating its timestamp, which means we
would no longer recognise these entries as racy and we would trust the
timestamp to tell us whether they have changed.

In order to work around this, git zeroes out the file-size field in
entries with the same timestamp as the index in order to force the next
diff to check the contents. Do so in libgit2 as well.
2015-06-16 08:40:45 +02:00
Edward Thomson
8147b1aff5 diff: introduce binary diff callbacks
Introduce a new binary diff callback to provide the actual binary
delta contents to callers.  Create this data from the diff contents
(instead of directly from the ODB) to support binary diffs including
the workdir, not just things coming out of the ODB.
2015-06-12 09:39:20 -04:00
Edward Thomson
9b3e41f72b index_add_all: remove conflicts when no wd file
If there exists a conflict in the index, but no file in the working
directory, this implies that the user wants to accept the resolution
by removing the file.  Thus, remove the conflict entry from the
index, instead of trying to add a (nonexistent) file.
2015-05-28 09:47:51 -04:00
Edward Thomson
9f545b9d71 introduce git_index_entry_is_conflict
It's not always obvious the mapping between stage level and
conflict-ness.  More importantly, this can lead otherwise sane
people to write constructs like `if (!git_index_entry_stage(entry))`,
which (while technically correct) is unreadable.

Provide a nice method to help avoid such messy thinking.
2015-05-28 09:47:31 -04:00
Edward Thomson
d67f270e58 index: validate mode of new conflicts 2015-05-28 09:43:57 -04:00
Edward Thomson
3ab5a65967 index: remove error message in non-error remove
If `git_index_remove_bypath` does no work, and returns an OK error
code, it should not set an error message.
2015-05-28 09:43:53 -04:00
Edward Thomson
ecd60a56eb conflicts: when adding conflicts, remove staged
When adding a conflict for some path, remove the staged entry.
Otherwise, an illegal index (with both stage 0 and high-stage
entries) would result.
2015-05-28 09:43:49 -04:00
Edward Thomson
cbfeecf33f git_index_add_all: don't recurse ignored dirs
No need to get reports about individual ignored files, having a
single ignored directory delta is enough.
2015-05-20 20:14:31 -04:00
Edward Thomson
fa9a969d80 index_add_all: include untracked files in new subdirs 2015-05-20 20:05:55 -04:00
Carlos Martín Nieto
2b2dfe80f0 index: include TYPECHANGE in the diff
Without this option, we would not be able to catch exec bit changes.
2015-05-14 15:23:12 +02:00