| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The diff header format is a strange beast in that it is inherently
unparseable in an unambiguous way. While parsing
a/file.txt b/file.txt
is obvious and trivially doable, parsing a diff header of
a/file b/file ab.txt b/file b/file ab.txt
is not (but in fact valid and created by git.git).
Due to that, we have relaxed our diff header parser in commit 80226b5f6
(patch_parse: allow parsing ambiguous patch headers, 2017-09-22), so
that we started to bail out when seeing diff headers with spaces in
their file names. Instead, we try to use the "---" and "+++" lines,
which are unambiguous.
In some cases, though, we neither have a useable file name from the
header nor from the "---" or "+++" lines. This is the case when we have
a deletion or addition of a file with spaces: the header is unparseable
and the other lines will simply show "/dev/null". This trips our parsing
logic when we try to extract the prefix (the "a/" part) that is being
used in the path line, where we unconditionally try to dereference a
NULL pointer in such a scenario.
We can fix this by simply not trying to parse the prefix in cases where
we have no useable path name. That'd leave the parsed patch without
either `old_prefix` or `new_prefix` populated. But in fact such cases
are already handled by users of the patch object, which simply opt to
use the default prefixes in that case.
|
| |
|
|
|
|
|
|
| |
Quiet down a warning from MSVC about how we're potentially losing data.
This is safe since we've explicitly tested that it's within the range of
0-100.
|
|
|
|
|
| |
Move to the `git_error` name in the internal API for error-related
functions.
|
|
|
|
|
|
|
| |
The function `parse_number` was replaced by `git_parse_advance_digit`
which is provided by the parser interface in commit 252f2eeee (parse:
implement and use `git_parse_advance_digit`, 2017-07-14). As there are
no remaining callers, remove it.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A lot of compilers nowadays generate warnings when there are cases in a
switch statement which implicitly fall through to the next case. To
avoid this warning, the last line in the case that is falling through
can have a comment matching a regular expression, where one possible
comment body would be `/* fall through */`.
An alternative to the comment would be an explicit attribute like e.g.
`[[clang::fallthrough]` or `__attribute__ ((fallthrough))`. But GCC only
introduced support for such an attribute recently with GCC 7. Thus, and
also because the fallthrough comment is supported by most compilers, we
settle for using comments instead.
One shortcoming of that method is that compilers are very strict about
that. Most interestingly, that comment _really_ has to be the last line.
In case a closing brace follows the comment, the heuristic will fail.
|
|\
| |
| | |
patch_parse: fix parsing unquoted filenames with spaces
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The git patch format allows for having unquoted paths with whitespaces
inside. This format becomes ambiguous to parse, e.g. in the following
example:
diff --git a/file b/with spaces.txt b/file b/with spaces.txt
While we cannot parse this in a correct way, we can instead use the
"---" and "+++" lines to retrieve the file names, as the path is not
followed by anything here but spans the complete remaining line. Because
of this, we can simply bail outwhen parsing the "diff --git" header here
without an actual error and then proceed to just take the paths from the
other headers.
|
| |
| |
| |
| |
| |
| |
| |
| | |
When parsing the "---" and "+++" line, we stop after the first
whitespace inside of the filename. But as files containing whitespaces
do not need to be quoted, we should instead use the complete line here.
This fixes parsing patches with unquoted paths with whitespaces.
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Strict aliasing rules dictate that for most data types, you are not
allowed to cast them to another data type and then access the casted
pointers. While this works just fine for most compilers, technically we
end up in undefined behaviour when we hurt that rule.
Our current refcounting code makes heavy use of casting and thus
violates that rule. While we didn't have any problems with that code,
Travis started spitting out a lot of warnings due to a change in their
toolchain. In the refcounting case, the code is also easy to fix:
as all refcounting-statements are actually macros, we can just access
the `rc` field directly instead of casting.
There are two outliers in our code where that doesn't work. Both the
`git_diff` and `git_patch` structures have specializations for generated
and parsed diffs/patches, which directly inherit from them. Because of
that, the refcounting code is only part of the base structure and not of
the children themselves. We can help that by instead passing their base
into `GIT_REFCOUNT_INC`, though.
|
|
|
|
|
|
|
| |
Upon initializing the parser context, we do not currently initialize the
current line, line length and line number. Do so in order to make the
interface easier to use and more obvious for future consumers of the
parsing API.
|
|
|
|
|
|
|
| |
Some code parts need to inspect the next few bytes without actually
consuming it yet, for example to examine what content it has to expect
next. Create a new function `git_parse_peek` which returns the next byte
without modifying the parsing context and use it at multiple call sites.
|
|
|
|
|
|
| |
The patch parsing code has multiple recurring patterns where we want to
parse an actual number. Create a new function `git_parse_advance_digit`
and use it to avoid code duplication.
|
|
|
|
|
|
|
|
| |
Instead of manually checking the parsing context's remaining length and
comparing the leading bytes with a specific string, we can simply re-use
the function `git_parse_ctx_contains_s`. Do so to avoid code duplication
and to further decouple patch parsing from the parsing context's struct
members.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The `git_patch_parse_ctx` encapsulates both parser state as well as
options specific to patch parsing. To advance this state and keep it
consistent, we provide a few functions which handle advancing the
current position and accessing bytes of the patch contents. In fact,
these functions are quite generic and not related to patch-parsing by
themselves. Seeing that we have similar logic inside of other modules,
it becomes quite enticing to extract this functionality into its own
parser module.
To do so, we create a new module `parse` with a central struct called
`git_parse_ctx`. It encapsulates both the content that is to be parsed
as well as its lengths and the current position. `git_patch_parse_ctx`
now only contains this `parse_ctx` only, which is then accessed whenever
we need to touch the current parser. This is the first step towards
re-using this functionality across other modules which require parsing
functionality and remove code-duplication.
|
|
|
|
|
|
|
|
| |
Patches which contain exact renames only will not contain an actual diff
body, but only a list of files that were renamed. Thus, the patch header
is immediately followed by the terminating sequence "-- ". We currently
do not recognize this character sequence as a possible terminating
sequence. Add it and create a test to catch the failure.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Our code parsing Git patch headers is rather lax in parsing headers of a
Git-style patch. Most notably, we do not care for the exact order in
which header lines appear and as such, we may parse patch files which
are not really valid after all. Furthermore, the state transitions
inside of the parser are not as obvious as they could be, making it
harder than required to follow its logic.
To improve upon this situation, this patch introduces a real state
machine to parse the patches. Instead of simply parsing each line
without caring for previous state and the exact ordering, we define a
set of states with their allowed transitions. This makes the patch
parser more strict in only allowing valid successions of header lines.
As the transition table is defined inside of a single structure with
the expected line, required state as well as the state that we end up
in, all state transitions are immediately obvious from just having a
look at this structure. This improves both maintainability and eases
reasoning about the patch parser.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Next to including several files, our "common.h" header also declares
various macros which are then used throughout the project. As such, we
have to make sure to always include this file first in all
implementation files. Otherwise, we might encounter problems or even
silent behavioural differences due to macros or defines not being
defined as they should be. So in fact, our header and implementation
files should make sure to always include "common.h" first.
This commit does so by establishing a common include pattern. Header
files inside of "src" will now always include "common.h" as its first
other file, separated by a newline from all the other includes to make
it stand out as special. There are two cases for the implementation
files. If they do have a matching header file, they will always include
this one first, leading to "common.h" being transitively included as
first file. If they do not have a matching header file, they instead
include "common.h" as first file themselves.
This fixes the outlined problems and will become our standard practice
for header and source files inside of the "src/" from now on.
|
|
|
|
|
|
|
|
| |
While parsing patch header lines, we iterate over each line and check if
the line has trailing garbage. What we do not check though is that the
line is actually a line ending with a trailing newline.
Fix this by checking the return code of `parse_advance_expected_str`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In a diff, the shortest possible hunk with a modification (that is, no
deletion) results from a file with only one line with a single character
which is removed. Thus the following hunk
@@ -1 +1 @@
-a
+
is the shortest valid hunk modifying a line. The function parsing the
hunk body though assumes that there must always be at least 4 bytes
present to make up a valid hunk, which is obviously wrong in this case.
The absolute minimum number of bytes required for a modification is
actually 2 bytes, that is the "+" and the following newline. Note: if
there is no trailing newline, the assumption will not be offended as the
diff will have a line "\ No trailing newline" at its end.
This patch fixes the issue by lowering the amount of bytes required.
|
| |
|
| |
|
|
|
|
|
|
| |
When creating and printing diffs, deal with binary deltas that have
binary data specially, versus diffs that have a binary file but lack the
actual binary data.
|
|
|
|
|
| |
Ensure that `git_patch_from_diff` can return the patch for parsed diffs,
not just generate a patch for a generated diff.
|
|
|
|
|
| |
Move `id_abbrev` to a more reasonable place where it packs more nicely
(before anybody starts using it).
|
| |
|
|
|
|
|
|
|
| |
When showing copy information because we are duplicating contents,
for example, when performing a `diff --find-copies-harder -M100 -B100`,
then show copy from/to lines in a patch, and do not show context.
Ensure that we can also parse such patches.
|
|
|
|
|
| |
Patches may have no hunks when there's no modifications (for example,
in a rename). Handle them.
|
| |
|
| |
|
|
|
|
| |
Parse diff files into a `git_diff` structure.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
| |
Handle prefixes (in terms of number of path components) for patch
parsing.
|
| |
|
| |
|
|
|
|
|
|
| |
When a text file is added or deleted, use the file names from the
`diff --git` header instead of the `---` or `+++` lines. This is
for compatibility with git.
|
|
|
|
|
| |
We may have parsed binary data, set the `SHOW_BINARY` flag which
indicates that we have actually computed a binary diff.
|
| |
|
|
|
|
|
|
| |
Now that `git_diff_delta` data can be produced by reading patch
file data, which may have an abbreviated oid, allow consumers to
know that the id is abbreviated.
|
| |
|