Now the ceiling_dirs are compared with their symbolic free version (like base_path).
The ceiling dirs check is now performed after getting the parent directory.
retrieve_device returns the file device for a given path (so that we can detect device change while walking through parent directories).
abspath returns a canonicalized path, symbolic link free.
retrieive_ceiling_directories_offset returns the biggest path offset that path match in the ceiling directory list (so that we can stop at ceiling directories).
Implemented find_unique_short_oid for pack backend, based on git sha1 lookup method;
finding an object given its full oid is just a particular case of searching
the unique object matching an oid prefix (short oid).
Added git_odb_read_unique_short_oid, which iterates over all the backends to
find and read the unique object matching the given oid prefix.
Added a git_object_lookup_short_oid method to find the unique object in
the repository matching a given oid prefix : it generalizes git_object_lookup
which now does nothing but calls git_object_lookup_short_oid.
A TREE extension with an entry count of -1 means that it was
invalidated and we should ignore it. Do so instead of returning an
error.
This fixes issue #202
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
There are two reasons why read_tree_internal might return a NULL
tree. The first one is a corrupt index, but the second one is an
invalidated TREE extension. Up to now, its only way to communicate
with its caller was through the return value being NULL or not.
Allow read_tree_internal to report its exit status independently from
the tree pointer.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Before this commit, malformed tag and signature were considered as
valid by the parser. See the test t3800-mktag.sh of git to see example
of malformed tag and signature.
If parse_section_header{,_ext} return an error, current_section
doesn't get allocated. Set it to NULL after freeing so we don't try to
free it again.
This fixes part 2-2 of Issue #210.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Simplify cfg_readline and at the same time fix it so that it does
really ignore empty lines.
This fixes point 2-1 of Issue #210
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
On error, it would free the configuration object even though it didn't
own that memory, which would cause a double-free.
This fixes the first part of Issue #210
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
"git_config_backend" have been renamed to "git_config_file", which
implements a generic interface to access a configuration file -- be it
either on disk, from a DB or whatever mumbojumbo.
I think this makes more sense.
Regarding "initialize" vs. "initialise", www.dict.cc says the first is American
English whereas the latter in British English. For consistency, we should
stick to American English.
When I changed it over to use different strings for the variable and
the name, cvar_name_normalize was left behind. Fix this and rename to
cvar_normalize_name to reflect the incompatible change.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Now we use a simple closed-addressing cache. Cuckoo hashing was creating
too many issues with race conditions. Fuck that.
Let's see what happens performance wise, we may have to roll back or
come up with another way to implement an efficient multi-threaded cache.
Configuration options can come from different sources. Currently,
there is only support for reading them from a flat file, but it might
make sense to read it from a database at some point.
Move the parsing code into src/config_file.c and create an include
file include/git2/config_backend.h to allow for other backends to be
developed.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Ok, this is the real deal. Hopefully. Here's how it's going to work:
- One main method, called `git__throw`, that sets the error
code and error message when an error happens.
This method must be called in every single place where an error
code was being returned previously, setting an error message
instead.
Example, instead of:
return GIT_EOBJCORRUPTED;
Use:
return git__throw(GIT_EOBJCORRUPTED,
"The object is missing a finalizing line feed");
And instead of:
[...] {
error = GIT_EOBJCORRUPTED;
goto cleanup;
}
Use:
[...] {
error = git__throw(GIT_EOBJCORRUPTED, "What an error!");
goto cleanup;
}
The **only** exception to this are the allocation methods, which
return NULL on failure but already set the message manually.
/* only place where an error code can be returned directly,
because the error message has already been set by the wrapper */
if (foo == NULL)
return GIT_ENOMEM;
- One secondary method, called `git__rethrow`, which can be used to
fine-grain an error message and build an error stack.
Example, instead of:
if ((error = foobar(baz)) < GIT_SUCCESS)
return error;
You can now do:
if ((error = foobar(baz)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to do a major operation");
The return of the `git_lasterror` method will be a string in the
shape of:
"Failed to do a major operation. (Failed to do an internal
operation)"
E.g.
"Failed to open the index. (Not enough permissions to access
'/path/to/index')."
NOTE: do not abuse this method. Try to write all `git__throw`
messages in a descriptive manner, to avoid having to rethrow them to
clarify their meaning.
This method should only be used in the places where the original
error message set by a subroutine is not specific enough.
It is encouraged to continue using this style as much possible to
enforce error propagation:
if ((error = foobar(baz)) < GIT_SUCCESS)
return error; /* `foobar` has set an error message, and
we are just propagating it */
The error handling revamp will take place in two phases:
- Phase 1: Replace all pieces of code that return direct error codes
with calls to `git__throw`. This can be done semi-automatically
using `ack` to locate all the error codes that must be replaced.
- Phase 2: Add some `git__rethrow` calls in those cases where the
original error messages are not specific enough.
Phase 1 is the main goal. A minor libgit2 release will be shipped once
Phase 1 is ready, and the work will start on gradually improving the
error handling mechanism by refining specific error messages.
OTHER NOTES:
- When writing error messages, please refrain from using weasel
words. They add verbosity to the message without giving any real
information. (<3 Emeric)
E.g.
"The reference file appears to be missing a carriage return"
Nope.
"The reference file is missing a carriage return"
Yes.
- When calling `git__throw`, please try to use more generic error
codes so we can eventually reduce the list of error codes to
something more reasonable. Feel free to add new, more generic error
codes if these are going to replace several of the old ones.
E.g.
return GIT_EREFCORRUPTED;
Can be turned into:
return git__throw(GIT_EOBJCORRUPTED,
"The reference is corrupted");
Win32 critical section objects (CRITICAL_SECTION) are not kernel objects.
Only kernel objects are destroyed by using CloseHandle. Critical sections
are supposed to be deleted with the DeleteCriticalSection API
(http://msdn.microsoft.com/en-us/library/ms682552(VS.85).aspx).
The section and variable names use different rules, so store them as
two different variables internally.
This will simplify the configuration-writing code as well later on,
but even with parsing, the code is simpler.
Take this opportunity to add a variable to the list directly when
parsing instead of passing through config_set.
A root commit is a commit whose branch (usually what HEAD points to)
doesn't exist (yet). This situation can happen when the commit is the
first after 1) a repository is initialized or 2) a orphan checkout has
been performed.
Take this opportunity to remove the symbolic link check, as
git_reference_resolve works on OID refs as well.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Typical use is git_reference_resolve(&ref, ref). Currently, if there is
an error, ref will point to NULL, causing the user to lose that
reference.
Always update resolved_ref instead of just on finding an OID ref,
storing the last valid reference in it.
This change helps simplify the code for allowing root commits.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Magic constant replaced by direct to-string covertion because of:
1) with value length 6 (040000 - subtree) final tree will be corrupted;
2) for wrong values length <6 final tree will be corrupted too.
Removed the optional `replace` argument, we now have 4 add methods:
`git_index_add`: add or update from path
`git_index_add2`: add or update from struct
`git_index_append`: add without replacing from path
`git_index_append2`: add without replacing from struct
Yes, this breaks the bindings.
New external functions:
- git_index_unmerged_entrycount: Counts the unmerged entries in
the index
- git_index_get_unmerged: Gets an unmerged entry from the index
by name
New internal functions:
- read_unmerged: Wrapper for read_unmerged_internal
- read_unmerged_internal: Reads unmerged entries from the index
if the index has the INDEX_EXT_UNMERGED_SIG set
- unmerged_srch: Search function for unmerged vector
- unmerged_cmp: Compare function for unmerged vector
New data structures:
- git_index now contains a git_vector unmerged that stores
unmerged entries
- git_index_entry_unmerged: Representation of an unmerged file
entry. It represents all three versions of the file at the
same time, with one name, three modes and three OIDs
When in the middle of a merge, the index needs to contain several files
with the same name. git_index_insert() used to prevent this by not adding a new entry if an entry with the same name already existed.
Most tags will have a timestamp of whenever the code is running and
dealing with time and timezones is error-prone. Optimize for this case
by adding a function which causes the signature to be created with a
current timestamp.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
git_repository_path() and git_repository_workdir() respectively return the path to the git repository and the working directory. Those paths are absolute and normalized.
Don't blindly pass the target type to git_tag_type2string as it will
give an empty string on GIT_OBJ_ANY which would cause us to create an
invalid tag object.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
We cannot assume that Redis is never going to return an error code; when
Reddit fails, we cannot crash our library, we need to handle the crash
gracefully.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
long int is a safer type than int unless the user knows that the
variable is going to be quite small.
The code has been reworked to use strtol instead of the more
complicated sscanf.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Many error paths freed their local data althought it is freed later on
when the end of the function notices that there was an error. This can
cause double frees and invalid memory access.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Make cvar_free return void instad of the next element, as it was
mostly a hack to make cvar_list_free shorter but it's now using the
list macros.
Also check if the input is NULL and return immediately in that case.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
There is no need to keep config file in memory until the the
configuration is freed. Free the buffer immediately after the
configuration has been parsed.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
If a variable name appears on its own in a line, it's assumed the
value is true. Store the variable name as NULL in that case.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
If a line ends at EOF there is no need to check for the newline
character and doing so will cause us to read memory beyond the
allocatd memory as we check for the Windows-style new-line, which is
two bytes long.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
If a variable value has the traditional continuation character (\) as
the last non-space character in the line, then we continue reading the
value on the next line.
Using more than two lines is also supported.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Make header and variable parse functions use their own buffers instead
of giving them the line they need to read as a parameter which they
mostly ignore.
This is in preparation for multiline configuration variables.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Streaming writes will no longer fail when writing to a backend that
doesn't support streaming writes but supports direct ones.
Now we create a fake stream on memory and then write it as a single
block using the backend `write` callback.
A variable name is stored internally with its section the way it
appeared in the configuration file in order to have the information
about what parts are case-sensitive inline.
Really implement parse_section_header_ext and move the assignment of
variables to config_parse.
The variable name matching is now done in a case-away way by
cvar_name_match and cvar_section_match. Before the user sees it, it's
normalized to the two- or three-dot version.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Such a list preserves the order the variables were first read in which
will be useful later for merging different data-sets. Furthermore,
reading and writing out the same configuration should not reorganize
the variables, which could happen when iterating through all the items
in a hash table.
A hash table is overkill for this small a data-set anyway.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
git_config_open shouldn't have to initialise variables that are only
used inside config_parse and its callees.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Config variables should be interpreted at run-time, as we don't know if a
zero means false or zero, or if yes means true or "yes".
As a variable has no intrinsic type, git_cvtype is gone and the public
API takes care of enforcing a few rules.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Allow any well-formed reference name to live under refs/ removing the
condition that they be under refs/{heads,tags,remotes}/ as was the
design of git.
An exception is made for HEAD which is allowed to contain an OID
reference in detached HEAD state.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Add internal reference create and rename functions which take a force
parameter, telling them to overwrite an existing reference if it
exists.
These functions try to update the reference if it's of the same type
as the one it's going to be replaced by. Otherwise the old reference
becomes invalid.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
These functions can be used to query or modify the variables in a
given configuration. No sanity checking is done on the variable names.
This is mostly meant as an API preview.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
If cfg_readline consumes the line, then parse_section_header will read
past it and if we read a character, parse_variable won't have the full
name.
This solution is a bit hackish, but it's the simplest way to get the
code to parse correctly.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Save the location of the name in section_out instead of returning it
as an int. Use the return code to signal success or failure.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Expose the tag parsing capabilities already present in the
library.
Exporting this function makes it possible to implement the
mktag command without duplicating this functionality.
Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
List all the references in the repository, calling a custom
callback for each one.
The listed references may be filtered by type, or using
a bitwise OR of several types. Use the magic value
`GIT_REF_LISTALL` to obtain all references, including
packed ones.
The `callback` function will be called for each of the references
in the repository, and will receive the name of the reference and
the `payload` value passed to this method.
The current behaviour of git_index_open{bare,inrepo}() is unexpected.
When an index is opened, an in-memory index object is created that is
linked to the index discovered by git_repository_open(). However, this
index object is empty, as the on-disk index is not read. To fully open
the on-disk index file, git_index_read() has to be called. This leads to
confusing behaviour. Consider the following code:
git_index *idx;
git_index_open_inrepo(&idx, repo);
git_index_write(idx);
You would expect this to have no effect, as the index is never
ostensibly manipulated. However, what actually happens is that the index
entries are removed from the on-disk index because the empty in-memory
index object created by open_inrepo() is written back to the disk.
This patch reads the index after opening it.
Temporary files when doing streaming writes are now stored inside the
Objects folder, to prevent issues when moving files between
disks/partitions.
Add support for block writes to the ODB again (for those backends that
cannot implement streaming).
When the system temporary folder is located on a different volume than the working directory into which libgit2 is executing, MoveFileEx() requires an additional flag.
Hey. Apologies in advance -- I broke your bindings.
This is a major commit that includes a long-overdue redesign of the
whole object-database structure. This is expected to be the last major
external API redesign of the library until the first non-alpha release.
Please get your bindings up to date with these changes. They will be
included in the next minor release. Sorry again!
Major features include:
- Real caching and refcounting on parsed objects
- Real caching and refcounting on objects read from the ODB
- Streaming writes & reads from the ODB
- Single-method writes for all object types
- The external API is now partially thread-safe
The speed increases are significant in all aspects, specially when
reading an object several times from the ODB (revwalking) and when
writing big objects to the ODB.
Here's a full changelog for the external API:
blob.h
------
- Remove `git_blob_new`
- Remove `git_blob_set_rawcontent`
- Remove `git_blob_set_rawcontent_fromfile`
- Rename `git_blob_writefile` -> `git_blob_create_fromfile`
- Change `git_blob_create_fromfile`:
The `path` argument is now relative to the repository's working dir
- Add `git_blob_create_frombuffer`
commit.h
--------
- Remove `git_commit_new`
- Remove `git_commit_add_parent`
- Remove `git_commit_set_message`
- Remove `git_commit_set_committer`
- Remove `git_commit_set_author`
- Remove `git_commit_set_tree`
- Add `git_commit_create`
- Add `git_commit_create_v`
- Add `git_commit_create_o`
- Add `git_commit_create_ov`
tag.h
-----
- Remove `git_tag_new`
- Remove `git_tag_set_target`
- Remove `git_tag_set_name`
- Remove `git_tag_set_tagger`
- Remove `git_tag_set_message`
- Add `git_tag_create`
- Add `git_tag_create_o`
tree.h
------
- Change `git_tree_entry_2object`:
New signature is `(git_object **object_out, git_repository *repo, git_tree_entry *entry)`
- Remove `git_tree_new`
- Remove `git_tree_add_entry`
- Remove `git_tree_remove_entry_byindex`
- Remove `git_tree_remove_entry_byname`
- Remove `git_tree_clearentries`
- Remove `git_tree_entry_set_id`
- Remove `git_tree_entry_set_name`
- Remove `git_tree_entry_set_attributes`
object.h
------------
- Remove `git_object_new
- Remove `git_object_write`
- Change `git_object_close`:
This method is now *mandatory*. Not closing an object causes a
memory leak.
odb.h
-----
- Remove type `git_rawobj`
- Remove `git_rawobj_close`
- Rename `git_rawobj_hash` -> `git_odb_hash`
- Change `git_odb_hash`:
New signature is `(git_oid *id, const void *data, size_t len, git_otype type)`
- Add type `git_odb_object`
- Add `git_odb_object_close`
- Change `git_odb_read`:
New signature is `(git_odb_object **out, git_odb *db, const git_oid *id)`
- Change `git_odb_read_header`:
New signature is `(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)`
- Remove `git_odb_write`
- Add `git_odb_open_wstream`
- Add `git_odb_open_rstream`
odb_backend.h
-------------
- Change type `git_odb_backend`:
New internal signatures are as follows
int (* read)(void **, size_t *, git_otype *, struct git_odb_backend *, const git_oid *)
int (* read_header)(size_t *, git_otype *, struct git_odb_backend *, const git_oid *)
int (* writestream)(struct git_odb_stream **, struct git_odb_backend *, size_t, git_otype)
int (* readstream)( struct git_odb_stream **, struct git_odb_backend *, const git_oid *)
- Add type `git_odb_stream`
- Add enum `git_odb_streammode`
Signed-off-by: Vicent Marti <tanoku@gmail.com>
We now depend on libpthread on all Unix platforms (should be installed
by default) and use a simple wrapper for Windows threads under Win32.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
It's no longer retarded. All object interdependencies are stored as OIDs
instead of actual objects. This should be hundreds of times faster,
specially on big repositories. Heck, who knows, maye it doesn't even
segfault -- wouldn't that be awesome?
What has changed on the API?
`git_commit_parent`, `git_commit_tree`, `git_tag_target` now return
their values through a pointer-to-pointer, and have an error code.
`git_commit_set_tree` and `git_tag_set_target` now return an error
code and may fail.
`git_repository_free__no_gc` has been deprecated because it's
stupid. Since there are no longer any interdependencies between
objects, we don't need internal reference counting, and GC
never fails or double-free's pointers.
`git_object_close` now does a very sane thing: marks an object
as unused. Closed objects will be eventually free'd from the
object cache based on LRU. Please use `git_object_close` from
the garbage collector `destroy` method on your bindings. It's
100% safe.
`git_repository_gc` is a new method that forces a garbage collector
pass through the repo, to free as many LRU objects as possible.
This is useful if we are running out of memory.
The new pack backend is an adaptation of the original git.git code in
`sha1_file.c`. It's slightly faster than the previous version and
severely less memory-hungry.
The call-stack of a normal pack backend query has been properly
documented in the top of the header for future reference. And by
properly I mean with ASCII diagrams 'n shit.
The new revision walker uses an internal Commit object storage system,
custom memory allocator and much improved topological and time sorting
algorithms. It's about 20x times faster than the previous implementation
when browsing big repositories.
The following external API calls have changed:
`git_revwalk_next` returns an OID instead of a full commit object.
The initial call to `git_revwalk_next` is no longer blocking when
iterating through a repo with a time-sorting mode.
Iterating with Topological or inverted modes still makes the initial
call blocking to preprocess the commit list, but this block should be
mostly unnoticeable on most repositories (topological preprocessing
times at 0.3s on the git.git repo).
`git_revwalk_push` and `git_revwalk_hide` now take an OID instead
of a full commit object.
Set of methods to find the minimal-length to uniquely identify every OID
in a list. Useful for GUI applications, commit logs and so on.
Includes stress test.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
Set of methods to find the minimal-length to uniquely identify every OID
in a list.
Includes stress test.
Signed-off-by: Vicent Marti <tanoku@gmail.com>