There is a little cleanup necessary from PR #843. Since the
new callbacks return `GIT_EUSER` we have to be a little careful
about return values when they are used internally to the library.
Also, callbacks should be checked for non-zero return values,
not just less than zero.
This updates all the `foreach()` type functions across the library
that take callbacks from the user to have a consistent behavior.
The rules are:
* A callback terminates the loop by returning any non-zero value
* Once the callback returns non-zero, it will not be called again
(i.e. the loop stops all iteration regardless of state)
* If the callback returns non-zero, the parent fn returns GIT_EUSER
* Although the parent returns GIT_EUSER, no error will be set in
the library and `giterr_last()` will return NULL if called.
This commit makes those changes across the library and adds tests
for most of the iteration APIs to make sure that they follow the
above rules.
Fixes#824
Exporting variables in a dynamic library is a PITA. Let's keep
these values internally and wrap them through a helper method.
This doesn't break the external API. @arrbee, aren't you glad I turned
the `GIT_ATTR_` macros into function macros? ✨
The 'git revert/cherry-pick/merge -n' commands leave .git/MERGE_MSG
behind so that git-commit can find it. As we don't yet support these
operations, users who are shelling out to let git perform these
operations haven't had a convenient way to get this message.
These functions allow the user to retrieve the message and remove it
when she's created the commit.
Instad of each transport having its own function and logic to get to
its refs, store them directly in transport.
Leverage the new gitno_buffer to make the parsing and storing of the
refs use common code and get rid of the git_protocol struct.
This allows us to add capabilitites to both at the same time, keeps
them in sync and removes a lot of code.
gitno_buffer now uses a callback to fill its buffer, allowing us to
use the same interface for git and http (which uses callbacks).
For the transition, http is going to keep its own logic until the
git/common code catches up with the implied multi_ack that http
has. This also has the side-effect of making the code cleaner and more
correct regardingt he protocol.
git.git uses an inlined hashcmp function instead of memcmp, since it
performes much better when comparing hashes (most hashes compared
diverge within the first byte).
Measurements and rationale for the curious reader:
http://thread.gmane.org/gmane.comp.version-control.git/172286
Renamed git_checkout_index to what it really was,
and removed duplicate code from clone.c. Added
git_checkout_ref, which updates HEAD and hands off
to git_checkout_head.
Added tests for the options the caller can pass to
git_checkout_*.
This makes sure that an error code returned by the callback function
of `git_tree_walk` will stop the iteration and get propagated back
to the caller verbatim.
Also, this adds a minor helper function `git_tree_entry_byoid` that
searches a `git_tree` for an entry with the given OID. This isn't
a fast function, but it's easier than writing the loop yourself as
an external user of the library.
A diff that is created with a NULL options parameter could result
in a NULL prefix string, but diff merge was unconditionally
strdup'ing it. I added a test to replicate the issue and then a
new method that does the right thing with NULL values.
Josh Triplett noticed libgit2 actually does preorder entries in
tree_walk_post instead of postorder. Also, we continued walking even
when an error occured in the callback.
Fix#773; also, allow both pre- and postorder walking.
Also removes the unnecessary check for filter
length, since git_filters_apply does the right
thing when there are none, and it's more efficient
than this.
Not all delta bases are available on the first try. By delaying
resolving all deltas until the end, we avoid decompressing some of the
data twice or even more times, saving effort and time.
The correct way to advertise out capabilities is by appending them to
the first 'want' line, using SP as separator, instead of NUL as the
server does. Inconsistent documentation lead to the use of NUL in
libgit2.
Fix this so we can request much more efficient packs from the
remote which reduces the indexing time considerably.
passing 0 to git_strol(32|64) let the implementation guess if it's
dealing with an octal number or a decimal one.
Let's make it safe and ensure that both 'HEAD@{010}' and 'HEAD@{10}'
point at the same commit.
This added a flag to the `git_repository_set_workdir()` function
that enables generation of a `.git` gitlink file that links the
new workdir to the parent repository. Essentially, the flag tells
the function to write out the changes to disk to permanently set
the workdir of the repository to the new path.
If you pass this flag as true, then setting the workdir to something
other than the default workdir (i.e. the parent of the .git repo
directory), will create a plain file named ".git" with the standard
gitlink contents "gitdir: <repo-path>", and also update the
"core.worktree" and "core.bare" config values.
Setting the workdir to the default repo workdir will clear the
core.worktree flag (but still permanently set core.bare to false).
BTW, the libgit2 API does not currently provide a function for
clearing the workdir and converting a non-bare repo into a bare one.
Adding a new config iteration function that let's you iterate
over just the config entries that match a particular regular
expression. The old foreach becomes a simple use of this with
an empty pattern.
This also fixes an apparent bug in the existing `git_config_foreach`
where returning a non-zero value from the iteration callback was
not correctly aborting the iteration and the returned value was
not being propogated back to the caller of foreach.
Added to tests to cover all these changes.
This makes it easy to take a buffer containing a path with relative
references (i.e. .. or . path segments) and resolve all of those
into a clean path. This can be applied to URLs as well as file
paths which can be useful.
As part of this, I made the drive-letter detection apply on all
platforms, not just windows. If you give a path that looks like
"c:/..." on any platform, it seems like we might as well detect
that as a rooted path. I suppose if you create a directory named
"x:" on another platform and want to use that as the beginning
of a relative path under the root directory of your repo, this
could cause a problem, but then it seems like you're asking for
trouble.
* `git_buf_rfind` (with tests and tests for `git_buf_rfind_next`)
* `git_buf_puts_escaped` and `git_buf_puts_escaped_regex` (with tests)
to copy strings into a buffer while injecting an escape sequence
(e.g. '\') in front of particular characters.
passing 0 to git_strol(32|64) let the implementation guess if it's
dealing with an octal number or a decimal one.
Let's make it safe and ensure that both 'HEAD@{010}' and 'HEAD@{10}'
point at the same commit.
On GNU, the d_name field of the dirent structure is defined as "char d_name[1]",
so we must allocate more than sizeof(struct dirent) bytes, just like on Sun.
Once a file is registered, there is no way to deregister it, even
after the structure that contains it is no longer needed and has been
freed. This may be the source of #624.
Allow and use the deregister function to remove our file from the
global list.
Currently, the first call of git_indexer_stream_add adds the data to the
underlying pack file and opens it for later use, but doesn't start
parsing the already available data.
This means, git_indexer_stream_finalize only works if
git_indexer_stream_add was called at least twice. Kill this limitation
by parsing available data immediately.
When the repository was reinitialized, every configuration change in repo_init_config() was directly performed against the file on the filesystem. However, a previous version of the configuration had previously been loaded in memory and attached to the repository, in repo_init_reinit().
The repository was unaware of the change and the stale cached version of the configuration never refreshed.
So far they only create a repo, setup the "origin"
remote, and fetch. The API probably needs work as
well; there's no way to get progress information
at this point.
Also uncovered a shortcoming; git_remote_download
doesn't fetch over local transport.
1. compile warning:
D:\libgit2.git\src\win32\posix_w32.c: In function 'p_open':
D:\libgit2.git\src\win32\posix_w32.c:235:10: warning: 'mode_t' is promoted to 'int' when passed through '...' [enabled by default]
D:\libgit2.git\src\win32\posix_w32.c:235:10: note: (so you should pass 'int' not 'mode_t' to 'va_arg')
D:\libgit2.git\src\win32\posix_w32.c:235:10: note: if this code is reached, the program will abort
2. test crash.
3. the above two issues are same root cause. please see http://www.eskimo.com/~scs/cclass/int/sx11c.html
The call to repo_init_reinit already takes care of opening the
repository and giving us a git_repository object to give to the
caller. There is no need to call git_repository_open again.
If we find several objects with the same prefix, we need to free the
memory where we stored the earlier object. Keep track of the raw.data
pointer across read_prefix calls and free it if we find another
object.
oid_for_tree_path may not always find the path in the tree, in which
case we need to return an error. The current code doesn't do this and
results in undefined behavior.
This fixes git_index_add and git_index_append to behave more like
core git, preserving old filemode data in the index when adding
and/or appending with core.filemode = false.
This also has placeholder support for core.symlinks and
core.ignorecase, but those flags are not implemented (well,
symlinks has partial support for preserving mode information in
the same way that git does, but it isn't tested).
git_commit() and git_tag() no longer prettify the
message by default. This has to be taken care of
by the caller.
This has the nice side effect of putting the
caller in position to actually choose to strip
the comments or not.
Needs AmigaOS.cmake now from CMake package at OS4Depot, or contents below:
--8<--
SET(AMIGA 1)
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC")
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared")
--8<--
When a configuration option is set, we didn't check to see whether
there was any escaping needed. Escape the available characters so we
can unescape them correctly when we read them.
On RAM: the .idx and .pack files become links to a .lock and the original download respectively.
Assume some feature (such as record locking) supported by SFS but not JXFS or RAM: is required.
When checking for a drive letter on windows, instead of using
isalpha(), it is better to just check for a..z and A..Z, I think,
particularly because the MS isalpha implementation appears to
assert when given an 0xFF byte.
There are three actual changes in this commit:
1. When the trailing newline of a file is removed in a diff, the
change will now be reported with `GIT_DIFF_LINE_DEL_EOFNL` passed
to the callback. Previously, the `ADD_EOFNL` constant was given
which was just an error in my understanding of when the various
circumstances arose. `GIT_DIFF_LINE_ADD_EOFNL` is deprecated and
should never be generated. A new newline is simply an `ADD`.
2. Rewrote the `diff_delta__merge_like_cgit` function that contains
the core logic of the `git_diff_merge` implementation. The new
version doesn't actually have significantly different behavior,
but the logic should be much more obvious, I think.
3. Fixed a bug in `git_diff_merge` where it freed a string pool
while some of the string data was still in use. This led to
`git_diff_print_patch` accessing memory that had been freed.
The rest of this commit contains improved documentation in `diff.h`
to make the behavior and the equivalencies with core git clearer,
and a bunch of new tests to cover the various cases, oh and a minor
simplification of `examples/diff.c`.
File modes were both not being ignored properly on platforms
where they should be ignored, nor be diffed consistently on
platforms where they are supported.
This change adds a number of diff and status filemode change
tests. This also makes sure that filemode-only changes are
included in the diff output when they occur and that filemode
changes are ignored successfully when core.filemode is false.
There is no code that automatically toggles core.filemode
based on the capabilities of the current platform, so the user
still needs to be careful in their .git/config file.
- Do not create new levels of fanout when creating notes from libgit2
- Insert a note in an existing matching fanout
- Remove a note from an existing fanout
- Cleanup git_note_read, git_note_remove, git_note_foreach, git_note_create methods in order use tree structures instead of tree_oids
git_status_file would always return GIT_ENOTFOUND for these files.
The underlying bug was that git__strcmp_cb, which is used by
git_path_with_stat_cmp to sort entries in the working directory,
compares strings based on unsigned chars (this is confirmed by the
strcmp(3) manpage), while git__prefixcmp, which is used by
workdir_iterator__entry_cmp to search for a path in the working
directory, compares strings based on char. So the sort puts this path at
the end of the list, while the search expects it to be at the beginning.
The fix was simply to make git__prefixcmp compare using unsigned chars,
just like strcmp(3). The rest of the change is just adding/updating
tests.
Converted an internal utility to return an oid,
rather than a tree entry (whose lifetime is tied
to the parent tree, which was freed before
returning).
The error codes from failed lookups of system and global files
on Windows were not consistent with the codes returned on other
platforms. This makes the error detection patterns match and
adds a unit test for the various errors.
This fixes two bugs:
* Issue #728 where git_status_file was not working for files
that contain spaces. This was caused by reusing the "fnmatch"
parsing code from ignore and attribute files to interpret the
"pathspec" that constrained the files to apply the status to.
In that code, unescaped whitespace was considered terminal to
the pattern, so a file with internal whitespace was excluded
from the matched files. The fix was to add a mode to that code
that allows spaces and tabs inside patterns. This mode only
comes into play when parsing in-memory strings.
* The other issue was undetected, but it was in the recently
added code to reload gitattributes / gitignores when they were
changed on disk. That code was not clearing out the old values
from the cached file content before reparsing which meant that
newly added patterns would be read in, but deleted patterns
would not be removed. The fix was to clear the vector of
patterns in a cached file before reparsing the file.
The function to convert UTF-16 to UTF-8 was only allocating a
buffer of wcslen(utf16str) bytes for the UTF-8 string, but that
is not sufficient if you have multibyte characters, and so when
those occured, the conversion was failing. This updates the
conversion functions to use the Win APIs to calculate the correct
buffer lengths.
Also fixes a comparison in the unit tests that would fail if
you did not have a particular environment variable set.
We used to consider a missing core.bare option to mean that the
repository was corrupt. This is too strict. Consider it a non-bare
repository if it's not set.
On Windows, we are having problems with home directories
that have non-ascii characters in them. This rewrites the
relevant code to fetch environment variables as UTF-16 and
then explicitly map then into UTF-8 for our internal usage.
If it's not available, an error saying so will be returned when trying
to use a https:// URL.
This also unifies a lot of the network code to use git_transport in
many places instead of an socket descriptor.
Local fetch isn't implemented yet. Don't segfault on call, but set a
dummy for negotiate_fetch and terminate gracefully.
Reported-by: Brad Harder <bch@methodlogic.net>
Creating a workdir iterator on a directory with absolutely
no files was returning an error (GIT_ENOTFOUND) instead of
an iterator for nothing. This fixes that and includes two
new tests that cover that case.
GProf shows `git_text_gather_stats` as the most expensive call
in large diffs. The function calculates a lot of information
that is not actually used and does not do so in a optimal
order. This introduces a tuned `git_buf_is_binary` function
that executes the same algorithm in a fraction of the time.
There was a bug where tracked files inside directories that were
inside ignored directories where not being found by status. To
make that a little clearer, if you have a .gitignore with:
ignore/
And then have the following files:
ignore/dir/tracked <-- actually a tracked file
ignore/dir/untracked <-- should be ignored
Then we would show the tracked file as being removed (because
when we got the to contained item "dir/" inside the ignored
directory, we decided it was safe to skip -- bzzt, wrong!).
This update is much more careful about checking that we are
not skipping over any prefix of a tracked item, regardless of
whether it is ignored or not.
As documented in diff.c, this commit does create behavior that
still differs from core git with regards to the handling of
untracked files contained inside ignored directories. With
libgit2, those files will just not show up in status or diff.
With core git, those files don't show up in status or diff
either *unless* they are explicitly ignored by a .gitignore
pattern in which case they show up as ignored files.
Needless to say, this is a local behavior difference only, so
it should not be important and (to me) the libgit2 behavior
seems more consistent.
Ported the win32 implementations of gmtime_r,
localtime_r, and gettimeofday to be part of the
posix compatibility layer, and fixed
git_signature_now to use them.
The goal of this work is to rewrite git_status_file to use the
same underlying code as git_status_foreach.
This is done in 3 phases:
1. Extend iterators to allow ranged iteration with start and
end prefixes for the range of file names to be covered.
2. Improve diff so that when there is a pathspec and there is
a common non-wildcard prefix of the pathspec, it will use
ranged iterators to minimize excess iteration.
3. Rewrite git_status_file to call git_status_foreach_ext
with a pathspec that covers just the one file being checked.
Since ranged iterators underlie the status & diff implementation,
this is actually fairly efficient. The workdir iterator does
end up loading the contents of all the directories down to the
single file, which should ideally be avoided, but it is pretty
good.
From the description of git_revwalk_reset in revwalk.h the function should
clear all pushed and hidden commits, and leave the walker in a blank state (just like at creation).
Apparently everything gets reseted appart of pushed commits (walk->one and walk->twos)
This fix should reset the walker properly.