mirror of
https://github.com/git/git.git
synced 2024-11-27 03:53:55 +08:00
Merge branch 'hw/doc-in-header'
* hw/doc-in-header: trace2: move doc to trace2.h submodule-config: move doc to submodule-config.h tree-walk: move doc to tree-walk.h trace: move doc to trace.h run-command: move doc to run-command.h parse-options: add link to doc file in parse-options.h credential: move doc to credential.h argv-array: move doc to argv-array.h cache: move doc to cache.h sigchain: move doc to sigchain.h pathspec: move doc to pathspec.h revision: move doc to revision.h attr: move doc to attr.h refs: move doc to refs.h remote: move doc to remote.h and refspec.h sha1-array: move doc to sha1-array.h merge: move doc to ll-merge.h graph: move doc to graph.h and graph.c dir: move doc to dir.h diff: move doc to diff.h and diffcore.h
This commit is contained in:
commit
26c816a67d
@ -17,7 +17,7 @@ revision walk is used for operations like `git log`.
|
||||
|
||||
- `Documentation/user-manual.txt` under "Hacking Git" contains some coverage of
|
||||
the revision walker in its various incarnations.
|
||||
- `Documentation/technical/api-revision-walking.txt`
|
||||
- `revision.h`
|
||||
- https://eagain.net/articles/git-for-computer-scientists/[Git for Computer Scientists]
|
||||
gives a good overview of the types of objects in Git and what your object
|
||||
walk is really describing.
|
||||
@ -119,9 +119,8 @@ parameters provided by the user over the CLI.
|
||||
|
||||
`nr` represents the number of `rev_cmdline_entry` present in the array.
|
||||
|
||||
`alloc` is used by the `ALLOC_GROW` macro. Check
|
||||
`Documentation/technical/api-allocation-growing.txt` - this variable is used to
|
||||
track the allocated size of the list.
|
||||
`alloc` is used by the `ALLOC_GROW` macro. Check `cache.h` - this variable is
|
||||
used to track the allocated size of the list.
|
||||
|
||||
Per entry, we find:
|
||||
|
||||
|
@ -19,8 +19,7 @@ from system-specific helpers, as well as prompting the user for
|
||||
usernames and passwords. The git-credential command exposes this
|
||||
interface to scripts which may want to retrieve, store, or prompt for
|
||||
credentials in the same manner as Git. The design of this scriptable
|
||||
interface models the internal C API; see
|
||||
link:technical/api-credentials.html[the Git credential API] for more
|
||||
interface models the internal C API; see credential.h for more
|
||||
background on the concepts.
|
||||
|
||||
git-credential takes an "action" option on the command-line (one of
|
||||
|
@ -186,8 +186,7 @@ CUSTOM HELPERS
|
||||
--------------
|
||||
|
||||
You can write your own custom helpers to interface with any system in
|
||||
which you keep credentials. See the documentation for Git's
|
||||
link:technical/api-credentials.html[credentials API] for details.
|
||||
which you keep credentials. See credential.h for details.
|
||||
|
||||
GIT
|
||||
---
|
||||
|
@ -1,39 +0,0 @@
|
||||
allocation growing API
|
||||
======================
|
||||
|
||||
Dynamically growing an array using realloc() is error prone and boring.
|
||||
|
||||
Define your array with:
|
||||
|
||||
* a pointer (`item`) that points at the array, initialized to `NULL`
|
||||
(although please name the variable based on its contents, not on its
|
||||
type);
|
||||
|
||||
* an integer variable (`alloc`) that keeps track of how big the current
|
||||
allocation is, initialized to `0`;
|
||||
|
||||
* another integer variable (`nr`) to keep track of how many elements the
|
||||
array currently has, initialized to `0`.
|
||||
|
||||
Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
|
||||
alloc)`. This ensures that the array can hold at least `n` elements by
|
||||
calling `realloc(3)` and adjusting `alloc` variable.
|
||||
|
||||
------------
|
||||
sometype *item;
|
||||
size_t nr;
|
||||
size_t alloc
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
if (we like item[i] already)
|
||||
return;
|
||||
|
||||
/* we did not like any existing one, so add one */
|
||||
ALLOC_GROW(item, nr + 1, alloc);
|
||||
item[nr++] = value you like;
|
||||
------------
|
||||
|
||||
You are responsible for updating the `nr` variable.
|
||||
|
||||
If you need to specify the number of elements to allocate explicitly
|
||||
then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`.
|
@ -1,65 +0,0 @@
|
||||
argv-array API
|
||||
==============
|
||||
|
||||
The argv-array API allows one to dynamically build and store
|
||||
NULL-terminated lists. An argv-array maintains the invariant that the
|
||||
`argv` member always points to a non-NULL array, and that the array is
|
||||
always NULL-terminated at the element pointed to by `argv[argc]`. This
|
||||
makes the result suitable for passing to functions expecting to receive
|
||||
argv from main(), or the link:api-run-command.html[run-command API].
|
||||
|
||||
The string-list API (documented in string-list.h) is similar, but cannot be
|
||||
used for these purposes; instead of storing a straight string pointer,
|
||||
it contains an item structure with a `util` field that is not compatible
|
||||
with the traditional argv interface.
|
||||
|
||||
Each `argv_array` manages its own memory. Any strings pushed into the
|
||||
array are duplicated, and all memory is freed by argv_array_clear().
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct argv_array`::
|
||||
|
||||
A single array. This should be initialized by assignment from
|
||||
`ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv`
|
||||
member contains the actual array; the `argc` member contains the
|
||||
number of elements in the array, not including the terminating
|
||||
NULL.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`argv_array_init`::
|
||||
Initialize an array. This is no different than assigning from
|
||||
`ARGV_ARRAY_INIT`.
|
||||
|
||||
`argv_array_push`::
|
||||
Push a copy of a string onto the end of the array.
|
||||
|
||||
`argv_array_pushl`::
|
||||
Push a list of strings onto the end of the array. The arguments
|
||||
should be a list of `const char *` strings, terminated by a NULL
|
||||
argument.
|
||||
|
||||
`argv_array_pushf`::
|
||||
Format a string and push it onto the end of the array. This is a
|
||||
convenience wrapper combining `strbuf_addf` and `argv_array_push`.
|
||||
|
||||
`argv_array_pushv`::
|
||||
Push a null-terminated array of strings onto the end of the array.
|
||||
|
||||
`argv_array_pop`::
|
||||
Remove the final element from the array. If there are no
|
||||
elements in the array, do nothing.
|
||||
|
||||
`argv_array_clear`::
|
||||
Free all memory associated with the array and return it to the
|
||||
initial, empty state.
|
||||
|
||||
`argv_array_detach`::
|
||||
Disconnect the `argv` member from the `argv_array` struct and
|
||||
return it. The caller is responsible for freeing the memory used
|
||||
by the array, and by the strings it references. After detaching,
|
||||
the `argv_array` is in a reinitialized state and can be pushed
|
||||
into again.
|
@ -1,271 +0,0 @@
|
||||
credentials API
|
||||
===============
|
||||
|
||||
The credentials API provides an abstracted way of gathering username and
|
||||
password credentials from the user (even though credentials in the wider
|
||||
world can take many forms, in this document the word "credential" always
|
||||
refers to a username and password pair).
|
||||
|
||||
This document describes two interfaces: the C API that the credential
|
||||
subsystem provides to the rest of Git, and the protocol that Git uses to
|
||||
communicate with system-specific "credential helpers". If you are
|
||||
writing Git code that wants to look up or prompt for credentials, see
|
||||
the section "C API" below. If you want to write your own helper, see
|
||||
the section on "Credential Helpers" below.
|
||||
|
||||
Typical setup
|
||||
-------------
|
||||
|
||||
------------
|
||||
+-----------------------+
|
||||
| Git code (C) |--- to server requiring --->
|
||||
| | authentication
|
||||
|.......................|
|
||||
| C credential API |--- prompt ---> User
|
||||
+-----------------------+
|
||||
^ |
|
||||
| pipe |
|
||||
| v
|
||||
+-----------------------+
|
||||
| Git credential helper |
|
||||
+-----------------------+
|
||||
------------
|
||||
|
||||
The Git code (typically a remote-helper) will call the C API to obtain
|
||||
credential data like a login/password pair (credential_fill). The
|
||||
API will itself call a remote helper (e.g. "git credential-cache" or
|
||||
"git credential-store") that may retrieve credential data from a
|
||||
store. If the credential helper cannot find the information, the C API
|
||||
will prompt the user. Then, the caller of the API takes care of
|
||||
contacting the server, and does the actual authentication.
|
||||
|
||||
C API
|
||||
-----
|
||||
|
||||
The credential C API is meant to be called by Git code which needs to
|
||||
acquire or store a credential. It is centered around an object
|
||||
representing a single credential and provides three basic operations:
|
||||
fill (acquire credentials by calling helpers and/or prompting the user),
|
||||
approve (mark a credential as successfully used so that it can be stored
|
||||
for later use), and reject (mark a credential as unsuccessful so that it
|
||||
can be erased from any persistent storage).
|
||||
|
||||
Data Structures
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
`struct credential`::
|
||||
|
||||
This struct represents a single username/password combination
|
||||
along with any associated context. All string fields should be
|
||||
heap-allocated (or NULL if they are not known or not applicable).
|
||||
The meaning of the individual context fields is the same as
|
||||
their counterparts in the helper protocol; see the section below
|
||||
for a description of each field.
|
||||
+
|
||||
The `helpers` member of the struct is a `string_list` of helpers. Each
|
||||
string specifies an external helper which will be run, in order, to
|
||||
either acquire or store credentials. See the section on credential
|
||||
helpers below. This list is filled-in by the API functions
|
||||
according to the corresponding configuration variables before
|
||||
consulting helpers, so there usually is no need for a caller to
|
||||
modify the helpers field at all.
|
||||
+
|
||||
This struct should always be initialized with `CREDENTIAL_INIT` or
|
||||
`credential_init`.
|
||||
|
||||
|
||||
Functions
|
||||
~~~~~~~~~
|
||||
|
||||
`credential_init`::
|
||||
|
||||
Initialize a credential structure, setting all fields to empty.
|
||||
|
||||
`credential_clear`::
|
||||
|
||||
Free any resources associated with the credential structure,
|
||||
returning it to a pristine initialized state.
|
||||
|
||||
`credential_fill`::
|
||||
|
||||
Instruct the credential subsystem to fill the username and
|
||||
password fields of the passed credential struct by first
|
||||
consulting helpers, then asking the user. After this function
|
||||
returns, the username and password fields of the credential are
|
||||
guaranteed to be non-NULL. If an error occurs, the function will
|
||||
die().
|
||||
|
||||
`credential_reject`::
|
||||
|
||||
Inform the credential subsystem that the provided credentials
|
||||
have been rejected. This will cause the credential subsystem to
|
||||
notify any helpers of the rejection (which allows them, for
|
||||
example, to purge the invalid credentials from storage). It
|
||||
will also free() the username and password fields of the
|
||||
credential and set them to NULL (readying the credential for
|
||||
another call to `credential_fill`). Any errors from helpers are
|
||||
ignored.
|
||||
|
||||
`credential_approve`::
|
||||
|
||||
Inform the credential subsystem that the provided credentials
|
||||
were successfully used for authentication. This will cause the
|
||||
credential subsystem to notify any helpers of the approval, so
|
||||
that they may store the result to be used again. Any errors
|
||||
from helpers are ignored.
|
||||
|
||||
`credential_from_url`::
|
||||
|
||||
Parse a URL into broken-down credential fields.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
The example below shows how the functions of the credential API could be
|
||||
used to login to a fictitious "foo" service on a remote host:
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
int foo_login(struct foo_connection *f)
|
||||
{
|
||||
int status;
|
||||
/*
|
||||
* Create a credential with some context; we don't yet know the
|
||||
* username or password.
|
||||
*/
|
||||
|
||||
struct credential c = CREDENTIAL_INIT;
|
||||
c.protocol = xstrdup("foo");
|
||||
c.host = xstrdup(f->hostname);
|
||||
|
||||
/*
|
||||
* Fill in the username and password fields by contacting
|
||||
* helpers and/or asking the user. The function will die if it
|
||||
* fails.
|
||||
*/
|
||||
credential_fill(&c);
|
||||
|
||||
/*
|
||||
* Otherwise, we have a username and password. Try to use it.
|
||||
*/
|
||||
status = send_foo_login(f, c.username, c.password);
|
||||
switch (status) {
|
||||
case FOO_OK:
|
||||
/* It worked. Store the credential for later use. */
|
||||
credential_accept(&c);
|
||||
break;
|
||||
case FOO_BAD_LOGIN:
|
||||
/* Erase the credential from storage so we don't try it
|
||||
* again. */
|
||||
credential_reject(&c);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Some other error occurred. We don't know if the
|
||||
* credential is good or bad, so report nothing to the
|
||||
* credential subsystem.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Free any associated resources. */
|
||||
credential_clear(&c);
|
||||
|
||||
return status;
|
||||
}
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
|
||||
Credential Helpers
|
||||
------------------
|
||||
|
||||
Credential helpers are programs executed by Git to fetch or save
|
||||
credentials from and to long-term storage (where "long-term" is simply
|
||||
longer than a single Git process; e.g., credentials may be stored
|
||||
in-memory for a few minutes, or indefinitely on disk).
|
||||
|
||||
Each helper is specified by a single string in the configuration
|
||||
variable `credential.helper` (and others, see linkgit:git-config[1]).
|
||||
The string is transformed by Git into a command to be executed using
|
||||
these rules:
|
||||
|
||||
1. If the helper string begins with "!", it is considered a shell
|
||||
snippet, and everything after the "!" becomes the command.
|
||||
|
||||
2. Otherwise, if the helper string begins with an absolute path, the
|
||||
verbatim helper string becomes the command.
|
||||
|
||||
3. Otherwise, the string "git credential-" is prepended to the helper
|
||||
string, and the result becomes the command.
|
||||
|
||||
The resulting command then has an "operation" argument appended to it
|
||||
(see below for details), and the result is executed by the shell.
|
||||
|
||||
Here are some example specifications:
|
||||
|
||||
----------------------------------------------------
|
||||
# run "git credential-foo"
|
||||
foo
|
||||
|
||||
# same as above, but pass an argument to the helper
|
||||
foo --bar=baz
|
||||
|
||||
# the arguments are parsed by the shell, so use shell
|
||||
# quoting if necessary
|
||||
foo --bar="whitespace arg"
|
||||
|
||||
# you can also use an absolute path, which will not use the git wrapper
|
||||
/path/to/my/helper --with-arguments
|
||||
|
||||
# or you can specify your own shell snippet
|
||||
!f() { echo "password=`cat $HOME/.secret`"; }; f
|
||||
----------------------------------------------------
|
||||
|
||||
Generally speaking, rule (3) above is the simplest for users to specify.
|
||||
Authors of credential helpers should make an effort to assist their
|
||||
users by naming their program "git-credential-$NAME", and putting it in
|
||||
the $PATH or $GIT_EXEC_PATH during installation, which will allow a user
|
||||
to enable it with `git config credential.helper $NAME`.
|
||||
|
||||
When a helper is executed, it will have one "operation" argument
|
||||
appended to its command line, which is one of:
|
||||
|
||||
`get`::
|
||||
|
||||
Return a matching credential, if any exists.
|
||||
|
||||
`store`::
|
||||
|
||||
Store the credential, if applicable to the helper.
|
||||
|
||||
`erase`::
|
||||
|
||||
Remove a matching credential, if any, from the helper's storage.
|
||||
|
||||
The details of the credential will be provided on the helper's stdin
|
||||
stream. The exact format is the same as the input/output format of the
|
||||
`git credential` plumbing command (see the section `INPUT/OUTPUT
|
||||
FORMAT` in linkgit:git-credential[1] for a detailed specification).
|
||||
|
||||
For a `get` operation, the helper should produce a list of attributes
|
||||
on stdout in the same format. A helper is free to produce a subset, or
|
||||
even no values at all if it has nothing useful to provide. Any provided
|
||||
attributes will overwrite those already known about by Git. If a helper
|
||||
outputs a `quit` attribute with a value of `true` or `1`, no further
|
||||
helpers will be consulted, nor will the user be prompted (if no
|
||||
credential has been provided, the operation will then fail).
|
||||
|
||||
For a `store` or `erase` operation, the helper's output is ignored.
|
||||
If it fails to perform the requested operation, it may complain to
|
||||
stderr to inform the user. If it does not support the requested
|
||||
operation (e.g., a read-only store), it should silently ignore the
|
||||
request.
|
||||
|
||||
If a helper receives any other operation, it should silently ignore the
|
||||
request. This leaves room for future operations to be added (older
|
||||
helpers will just ignore the new requests).
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
linkgit:gitcredentials[7]
|
||||
|
||||
linkgit:git-config[1] (See configuration variables `credential.*`)
|
@ -1,174 +0,0 @@
|
||||
diff API
|
||||
========
|
||||
|
||||
The diff API is for programs that compare two sets of files (e.g. two
|
||||
trees, one tree and the index) and present the found difference in
|
||||
various ways. The calling program is responsible for feeding the API
|
||||
pairs of files, one from the "old" set and the corresponding one from
|
||||
"new" set, that are different. The library called through this API is
|
||||
called diffcore, and is responsible for two things.
|
||||
|
||||
* finding total rewrites (`-B`), renames (`-M`) and copies (`-C`), and
|
||||
changes that touch a string (`-S`), as specified by the caller.
|
||||
|
||||
* outputting the differences in various formats, as specified by the
|
||||
caller.
|
||||
|
||||
Calling sequence
|
||||
----------------
|
||||
|
||||
* Prepare `struct diff_options` to record the set of diff options, and
|
||||
then call `repo_diff_setup()` to initialize this structure. This
|
||||
sets up the vanilla default.
|
||||
|
||||
* Fill in the options structure to specify desired output format, rename
|
||||
detection, etc. `diff_opt_parse()` can be used to parse options given
|
||||
from the command line in a way consistent with existing git-diff
|
||||
family of programs.
|
||||
|
||||
* Call `diff_setup_done()`; this inspects the options set up so far for
|
||||
internal consistency and make necessary tweaking to it (e.g. if
|
||||
textual patch output was asked, recursive behaviour is turned on);
|
||||
the callback set_default in diff_options can be used to tweak this more.
|
||||
|
||||
* As you find different pairs of files, call `diff_change()` to feed
|
||||
modified files, `diff_addremove()` to feed created or deleted files,
|
||||
or `diff_unmerge()` to feed a file whose state is 'unmerged' to the
|
||||
API. These are thin wrappers to a lower-level `diff_queue()` function
|
||||
that is flexible enough to record any of these kinds of changes.
|
||||
|
||||
* Once you finish feeding the pairs of files, call `diffcore_std()`.
|
||||
This will tell the diffcore library to go ahead and do its work.
|
||||
|
||||
* Calling `diff_flush()` will produce the output.
|
||||
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
* `struct diff_filespec`
|
||||
|
||||
This is the internal representation for a single file (blob). It
|
||||
records the blob object name (if known -- for a work tree file it
|
||||
typically is a NUL SHA-1), filemode and pathname. This is what the
|
||||
`diff_addremove()`, `diff_change()` and `diff_unmerge()` synthesize and
|
||||
feed `diff_queue()` function with.
|
||||
|
||||
* `struct diff_filepair`
|
||||
|
||||
This records a pair of `struct diff_filespec`; the filespec for a file
|
||||
in the "old" set (i.e. preimage) is called `one`, and the filespec for a
|
||||
file in the "new" set (i.e. postimage) is called `two`. A change that
|
||||
represents file creation has NULL in `one`, and file deletion has NULL
|
||||
in `two`.
|
||||
|
||||
A `filepair` starts pointing at `one` and `two` that are from the same
|
||||
filename, but `diffcore_std()` can break pairs and match component
|
||||
filespecs with other filespecs from a different filepair to form new
|
||||
filepair. This is called 'rename detection'.
|
||||
|
||||
* `struct diff_queue`
|
||||
|
||||
This is a collection of filepairs. Notable members are:
|
||||
|
||||
`queue`::
|
||||
|
||||
An array of pointers to `struct diff_filepair`. This
|
||||
dynamically grows as you add filepairs;
|
||||
|
||||
`alloc`::
|
||||
|
||||
The allocated size of the `queue` array;
|
||||
|
||||
`nr`::
|
||||
|
||||
The number of elements in the `queue` array.
|
||||
|
||||
|
||||
* `struct diff_options`
|
||||
|
||||
This describes the set of options the calling program wants to affect
|
||||
the operation of diffcore library with.
|
||||
|
||||
Notable members are:
|
||||
|
||||
`output_format`::
|
||||
The output format used when `diff_flush()` is run.
|
||||
|
||||
`context`::
|
||||
Number of context lines to generate in patch output.
|
||||
|
||||
`break_opt`, `detect_rename`, `rename-score`, `rename_limit`::
|
||||
Affects the way detection logic for complete rewrites, renames
|
||||
and copies.
|
||||
|
||||
`abbrev`::
|
||||
Number of hexdigits to abbreviate raw format output to.
|
||||
|
||||
`pickaxe`::
|
||||
A constant string (can and typically does contain newlines to
|
||||
look for a block of text, not just a single line) to filter out
|
||||
the filepairs that do not change the number of strings contained
|
||||
in its preimage and postimage of the diff_queue.
|
||||
|
||||
`flags`::
|
||||
This is mostly a collection of boolean options that affects the
|
||||
operation, but some do not have anything to do with the diffcore
|
||||
library.
|
||||
|
||||
`touched_flags`::
|
||||
Records whether a flag has been changed due to user request
|
||||
(rather than just set/unset by default).
|
||||
|
||||
`set_default`::
|
||||
Callback which allows tweaking the options in diff_setup_done().
|
||||
|
||||
BINARY, TEXT;;
|
||||
Affects the way how a file that is seemingly binary is treated.
|
||||
|
||||
FULL_INDEX;;
|
||||
Tells the patch output format not to use abbreviated object
|
||||
names on the "index" lines.
|
||||
|
||||
FIND_COPIES_HARDER;;
|
||||
Tells the diffcore library that the caller is feeding unchanged
|
||||
filepairs to allow copies from unmodified files be detected.
|
||||
|
||||
COLOR_DIFF;;
|
||||
Output should be colored.
|
||||
|
||||
COLOR_DIFF_WORDS;;
|
||||
Output is a colored word-diff.
|
||||
|
||||
NO_INDEX;;
|
||||
Tells diff-files that the input is not tracked files but files
|
||||
in random locations on the filesystem.
|
||||
|
||||
ALLOW_EXTERNAL;;
|
||||
Tells output routine that it is Ok to call user specified patch
|
||||
output routine. Plumbing disables this to ensure stable output.
|
||||
|
||||
QUIET;;
|
||||
Do not show any output.
|
||||
|
||||
REVERSE_DIFF;;
|
||||
Tells the library that the calling program is feeding the
|
||||
filepairs reversed; `one` is two, and `two` is one.
|
||||
|
||||
EXIT_WITH_STATUS;;
|
||||
For communication between the calling program and the options
|
||||
parser; tell the calling program to signal the presence of
|
||||
difference using program exit code.
|
||||
|
||||
HAS_CHANGES;;
|
||||
Internal; used for optimization to see if there is any change.
|
||||
|
||||
SILENT_ON_REMOVE;;
|
||||
Affects if diff-files shows removed files.
|
||||
|
||||
RECURSIVE, TREE_IN_RECURSIVE;;
|
||||
Tells if tree traversal done by tree-diff should recursively
|
||||
descend into a tree object pair that are different in preimage
|
||||
and postimage set.
|
||||
|
||||
(JC)
|
@ -1,130 +0,0 @@
|
||||
directory listing API
|
||||
=====================
|
||||
|
||||
The directory listing API is used to enumerate paths in the work tree,
|
||||
optionally taking `.git/info/exclude` and `.gitignore` files per
|
||||
directory into account.
|
||||
|
||||
Data structure
|
||||
--------------
|
||||
|
||||
`struct dir_struct` structure is used to pass directory traversal
|
||||
options to the library and to record the paths discovered. A single
|
||||
`struct dir_struct` is used regardless of whether or not the traversal
|
||||
recursively descends into subdirectories.
|
||||
|
||||
The notable options are:
|
||||
|
||||
`exclude_per_dir`::
|
||||
|
||||
The name of the file to be read in each directory for excluded
|
||||
files (typically `.gitignore`).
|
||||
|
||||
`flags`::
|
||||
|
||||
A bit-field of options:
|
||||
|
||||
`DIR_SHOW_IGNORED`:::
|
||||
|
||||
Return just ignored files in `entries[]`, not untracked
|
||||
files. This flag is mutually exclusive with
|
||||
`DIR_SHOW_IGNORED_TOO`.
|
||||
|
||||
`DIR_SHOW_IGNORED_TOO`:::
|
||||
|
||||
Similar to `DIR_SHOW_IGNORED`, but return ignored files in
|
||||
`ignored[]` in addition to untracked files in
|
||||
`entries[]`. This flag is mutually exclusive with
|
||||
`DIR_SHOW_IGNORED`.
|
||||
|
||||
`DIR_KEEP_UNTRACKED_CONTENTS`:::
|
||||
|
||||
Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is set, the
|
||||
untracked contents of untracked directories are also returned in
|
||||
`entries[]`.
|
||||
|
||||
`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`:::
|
||||
|
||||
Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if
|
||||
this is set, returns ignored files and directories that match
|
||||
an exclude pattern. If a directory matches an exclude pattern,
|
||||
then the directory is returned and the contained paths are
|
||||
not. A directory that does not match an exclude pattern will
|
||||
not be returned even if all of its contents are ignored. In
|
||||
this case, the contents are returned as individual entries.
|
||||
+
|
||||
If this is set, files and directories that explicitly match an ignore
|
||||
pattern are reported. Implicitly ignored directories (directories that
|
||||
do not match an ignore pattern, but whose contents are all ignored)
|
||||
are not reported, instead all of the contents are reported.
|
||||
|
||||
`DIR_COLLECT_IGNORED`:::
|
||||
|
||||
Special mode for git-add. Return ignored files in `ignored[]` and
|
||||
untracked files in `entries[]`. Only returns ignored files that match
|
||||
pathspec exactly (no wildcards). Does not recurse into ignored
|
||||
directories.
|
||||
|
||||
`DIR_SHOW_OTHER_DIRECTORIES`:::
|
||||
|
||||
Include a directory that is not tracked.
|
||||
|
||||
`DIR_HIDE_EMPTY_DIRECTORIES`:::
|
||||
|
||||
Do not include a directory that is not tracked and is empty.
|
||||
|
||||
`DIR_NO_GITLINKS`:::
|
||||
|
||||
If set, recurse into a directory that looks like a Git
|
||||
directory. Otherwise it is shown as a directory.
|
||||
|
||||
The result of the enumeration is left in these fields:
|
||||
|
||||
`entries[]`::
|
||||
|
||||
An array of `struct dir_entry`, each element of which describes
|
||||
a path.
|
||||
|
||||
`nr`::
|
||||
|
||||
The number of members in `entries[]` array.
|
||||
|
||||
`alloc`::
|
||||
|
||||
Internal use; keeps track of allocation of `entries[]` array.
|
||||
|
||||
`ignored[]`::
|
||||
|
||||
An array of `struct dir_entry`, used for ignored paths with the
|
||||
`DIR_SHOW_IGNORED_TOO` and `DIR_COLLECT_IGNORED` flags.
|
||||
|
||||
`ignored_nr`::
|
||||
|
||||
The number of members in `ignored[]` array.
|
||||
|
||||
Calling sequence
|
||||
----------------
|
||||
|
||||
Note: index may be looked at for .gitignore files that are CE_SKIP_WORKTREE
|
||||
marked. If you to exclude files, make sure you have loaded index first.
|
||||
|
||||
* Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
|
||||
sizeof(dir))`.
|
||||
|
||||
* To add single exclude pattern, call `add_pattern_list()` and then
|
||||
`add_pattern()`.
|
||||
|
||||
* To add patterns from a file (e.g. `.git/info/exclude`), call
|
||||
`add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. A
|
||||
short-hand function `setup_standard_excludes()` can be used to set
|
||||
up the standard set of exclude settings.
|
||||
|
||||
* Set options described in the Data Structure section above.
|
||||
|
||||
* Call `read_directory()`.
|
||||
|
||||
* Use `dir.entries[]`.
|
||||
|
||||
* Call `clear_directory()` when none of the contained elements are no longer in use.
|
||||
|
||||
(JC)
|
@ -1,154 +0,0 @@
|
||||
gitattributes API
|
||||
=================
|
||||
|
||||
gitattributes mechanism gives a uniform way to associate various
|
||||
attributes to set of paths.
|
||||
|
||||
|
||||
Data Structure
|
||||
--------------
|
||||
|
||||
`struct git_attr`::
|
||||
|
||||
An attribute is an opaque object that is identified by its name.
|
||||
Pass the name to `git_attr()` function to obtain the object of
|
||||
this type. The internal representation of this structure is
|
||||
of no interest to the calling programs. The name of the
|
||||
attribute can be retrieved by calling `git_attr_name()`.
|
||||
|
||||
`struct attr_check_item`::
|
||||
|
||||
This structure represents one attribute and its value.
|
||||
|
||||
`struct attr_check`::
|
||||
|
||||
This structure represents a collection of `attr_check_item`.
|
||||
It is passed to `git_check_attr()` function, specifying the
|
||||
attributes to check, and receives their values.
|
||||
|
||||
|
||||
Attribute Values
|
||||
----------------
|
||||
|
||||
An attribute for a path can be in one of four states: Set, Unset,
|
||||
Unspecified or set to a string, and `.value` member of `struct
|
||||
attr_check_item` records it. There are three macros to check these:
|
||||
|
||||
`ATTR_TRUE()`::
|
||||
|
||||
Returns true if the attribute is Set for the path.
|
||||
|
||||
`ATTR_FALSE()`::
|
||||
|
||||
Returns true if the attribute is Unset for the path.
|
||||
|
||||
`ATTR_UNSET()`::
|
||||
|
||||
Returns true if the attribute is Unspecified for the path.
|
||||
|
||||
If none of the above returns true, `.value` member points at a string
|
||||
value of the attribute for the path.
|
||||
|
||||
|
||||
Querying Specific Attributes
|
||||
----------------------------
|
||||
|
||||
* Prepare `struct attr_check` using attr_check_initl()
|
||||
function, enumerating the names of attributes whose values you are
|
||||
interested in, terminated with a NULL pointer. Alternatively, an
|
||||
empty `struct attr_check` can be prepared by calling
|
||||
`attr_check_alloc()` function and then attributes you want to
|
||||
ask about can be added to it with `attr_check_append()`
|
||||
function.
|
||||
|
||||
* Call `git_check_attr()` to check the attributes for the path.
|
||||
|
||||
* Inspect `attr_check` structure to see how each of the
|
||||
attribute in the array is defined for the path.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
To see how attributes "crlf" and "ident" are set for different paths.
|
||||
|
||||
. Prepare a `struct attr_check` with two elements (because
|
||||
we are checking two attributes):
|
||||
|
||||
------------
|
||||
static struct attr_check *check;
|
||||
static void setup_check(void)
|
||||
{
|
||||
if (check)
|
||||
return; /* already done */
|
||||
check = attr_check_initl("crlf", "ident", NULL);
|
||||
}
|
||||
------------
|
||||
|
||||
. Call `git_check_attr()` with the prepared `struct attr_check`:
|
||||
|
||||
------------
|
||||
const char *path;
|
||||
|
||||
setup_check();
|
||||
git_check_attr(path, check);
|
||||
------------
|
||||
|
||||
. Act on `.value` member of the result, left in `check->items[]`:
|
||||
|
||||
------------
|
||||
const char *value = check->items[0].value;
|
||||
|
||||
if (ATTR_TRUE(value)) {
|
||||
The attribute is Set, by listing only the name of the
|
||||
attribute in the gitattributes file for the path.
|
||||
} else if (ATTR_FALSE(value)) {
|
||||
The attribute is Unset, by listing the name of the
|
||||
attribute prefixed with a dash - for the path.
|
||||
} else if (ATTR_UNSET(value)) {
|
||||
The attribute is neither set nor unset for the path.
|
||||
} else if (!strcmp(value, "input")) {
|
||||
If none of ATTR_TRUE(), ATTR_FALSE(), or ATTR_UNSET() is
|
||||
true, the value is a string set in the gitattributes
|
||||
file for the path by saying "attr=value".
|
||||
} else if (... other check using value as string ...) {
|
||||
...
|
||||
}
|
||||
------------
|
||||
|
||||
To see how attributes in argv[] are set for different paths, only
|
||||
the first step in the above would be different.
|
||||
|
||||
------------
|
||||
static struct attr_check *check;
|
||||
static void setup_check(const char **argv)
|
||||
{
|
||||
check = attr_check_alloc();
|
||||
while (*argv) {
|
||||
struct git_attr *attr = git_attr(*argv);
|
||||
attr_check_append(check, attr);
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
------------
|
||||
|
||||
|
||||
Querying All Attributes
|
||||
-----------------------
|
||||
|
||||
To get the values of all attributes associated with a file:
|
||||
|
||||
* Prepare an empty `attr_check` structure by calling
|
||||
`attr_check_alloc()`.
|
||||
|
||||
* Call `git_all_attrs()`, which populates the `attr_check`
|
||||
with the attributes attached to the path.
|
||||
|
||||
* Iterate over the `attr_check.items[]` array to examine
|
||||
the attribute names and values. The name of the attribute
|
||||
described by an `attr_check.items[]` object can be retrieved via
|
||||
`git_attr_name(check->items[i].attr)`. (Please note that no items
|
||||
will be returned for unset attributes, so `ATTR_UNSET()` will return
|
||||
false for all returned `attr_check.items[]` objects.)
|
||||
|
||||
* Free the `attr_check` struct by calling `attr_check_free()`.
|
@ -1,173 +0,0 @@
|
||||
history graph API
|
||||
=================
|
||||
|
||||
The graph API is used to draw a text-based representation of the commit
|
||||
history. The API generates the graph in a line-by-line fashion.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
Core functions:
|
||||
|
||||
* `graph_init()` creates a new `struct git_graph`
|
||||
|
||||
* `graph_update()` moves the graph to a new commit.
|
||||
|
||||
* `graph_next_line()` outputs the next line of the graph into a strbuf. It
|
||||
does not add a terminating newline.
|
||||
|
||||
* `graph_padding_line()` outputs a line of vertical padding in the graph. It
|
||||
is similar to `graph_next_line()`, but is guaranteed to never print the line
|
||||
containing the current commit. Where `graph_next_line()` would print the
|
||||
commit line next, `graph_padding_line()` prints a line that simply extends
|
||||
all branch lines downwards one row, leaving their positions unchanged.
|
||||
|
||||
* `graph_is_commit_finished()` determines if the graph has output all lines
|
||||
necessary for the current commit. If `graph_update()` is called before all
|
||||
lines for the current commit have been printed, the next call to
|
||||
`graph_next_line()` will output an ellipsis, to indicate that a portion of
|
||||
the graph was omitted.
|
||||
|
||||
The following utility functions are wrappers around `graph_next_line()` and
|
||||
`graph_is_commit_finished()`. They always print the output to stdout.
|
||||
They can all be called with a NULL graph argument, in which case no graph
|
||||
output will be printed.
|
||||
|
||||
* `graph_show_commit()` calls `graph_next_line()` and
|
||||
`graph_is_commit_finished()` until one of them return non-zero. This prints
|
||||
all graph lines up to, and including, the line containing this commit.
|
||||
Output is printed to stdout. The last line printed does not contain a
|
||||
terminating newline.
|
||||
|
||||
* `graph_show_oneline()` calls `graph_next_line()` and prints the result to
|
||||
stdout. The line printed does not contain a terminating newline.
|
||||
|
||||
* `graph_show_padding()` calls `graph_padding_line()` and prints the result to
|
||||
stdout. The line printed does not contain a terminating newline.
|
||||
|
||||
* `graph_show_remainder()` calls `graph_next_line()` until
|
||||
`graph_is_commit_finished()` returns non-zero. Output is printed to stdout.
|
||||
The last line printed does not contain a terminating newline. Returns 1 if
|
||||
output was printed, and 0 if no output was necessary.
|
||||
|
||||
* `graph_show_strbuf()` prints the specified strbuf to stdout, prefixing all
|
||||
lines but the first with a graph line. The caller is responsible for
|
||||
ensuring graph output for the first line has already been printed to stdout.
|
||||
(This can be done with `graph_show_commit()` or `graph_show_oneline()`.) If
|
||||
a NULL graph is supplied, the strbuf is printed as-is.
|
||||
|
||||
* `graph_show_commit_msg()` is similar to `graph_show_strbuf()`, but it also
|
||||
prints the remainder of the graph, if more lines are needed after the strbuf
|
||||
ends. It is better than directly calling `graph_show_strbuf()` followed by
|
||||
`graph_show_remainder()` since it properly handles buffers that do not end in
|
||||
a terminating newline. The output printed by `graph_show_commit_msg()` will
|
||||
end in a newline if and only if the strbuf ends in a newline.
|
||||
|
||||
Data structure
|
||||
--------------
|
||||
`struct git_graph` is an opaque data type used to store the current graph
|
||||
state.
|
||||
|
||||
Calling sequence
|
||||
----------------
|
||||
|
||||
* Create a `struct git_graph` by calling `graph_init()`. When using the
|
||||
revision walking API, this is done automatically by `setup_revisions()` if
|
||||
the '--graph' option is supplied.
|
||||
|
||||
* Use the revision walking API to walk through a group of contiguous commits.
|
||||
The `get_revision()` function automatically calls `graph_update()` each time
|
||||
it is invoked.
|
||||
|
||||
* For each commit, call `graph_next_line()` repeatedly, until
|
||||
`graph_is_commit_finished()` returns non-zero. Each call to
|
||||
`graph_next_line()` will output a single line of the graph. The resulting
|
||||
lines will not contain any newlines. `graph_next_line()` returns 1 if the
|
||||
resulting line contains the current commit, or 0 if this is merely a line
|
||||
needed to adjust the graph before or after the current commit. This return
|
||||
value can be used to determine where to print the commit summary information
|
||||
alongside the graph output.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
* `graph_update()` must be called with commits in topological order. It should
|
||||
not be called on a commit if it has already been invoked with an ancestor of
|
||||
that commit, or the graph output will be incorrect.
|
||||
|
||||
* `graph_update()` must be called on a contiguous group of commits. If
|
||||
`graph_update()` is called on a particular commit, it should later be called
|
||||
on all parents of that commit. Parents must not be skipped, or the graph
|
||||
output will appear incorrect.
|
||||
+
|
||||
`graph_update()` may be used on a pruned set of commits only if the parent list
|
||||
has been rewritten so as to include only ancestors from the pruned set.
|
||||
|
||||
* The graph API does not currently support reverse commit ordering. In
|
||||
order to implement reverse ordering, the graphing API needs an
|
||||
(efficient) mechanism to find the children of a commit.
|
||||
|
||||
Sample usage
|
||||
------------
|
||||
|
||||
------------
|
||||
struct commit *commit;
|
||||
struct git_graph *graph = graph_init(opts);
|
||||
|
||||
while ((commit = get_revision(opts)) != NULL) {
|
||||
while (!graph_is_commit_finished(graph))
|
||||
{
|
||||
struct strbuf sb;
|
||||
int is_commit_line;
|
||||
|
||||
strbuf_init(&sb, 0);
|
||||
is_commit_line = graph_next_line(graph, &sb);
|
||||
fputs(sb.buf, stdout);
|
||||
|
||||
if (is_commit_line)
|
||||
log_tree_commit(opts, commit);
|
||||
else
|
||||
putchar(opts->diffopt.line_termination);
|
||||
}
|
||||
}
|
||||
------------
|
||||
|
||||
Sample output
|
||||
-------------
|
||||
|
||||
The following is an example of the output from the graph API. This output does
|
||||
not include any commit summary information--callers are responsible for
|
||||
outputting that information, if desired.
|
||||
|
||||
------------
|
||||
*
|
||||
*
|
||||
*
|
||||
|\
|
||||
* |
|
||||
| | *
|
||||
| \ \
|
||||
| \ \
|
||||
*-. \ \
|
||||
|\ \ \ \
|
||||
| | * | |
|
||||
| | | | | *
|
||||
| | | | | *
|
||||
| | | | | *
|
||||
| | | | | |\
|
||||
| | | | | | *
|
||||
| * | | | | |
|
||||
| | | | | * \
|
||||
| | | | | |\ |
|
||||
| | | | * | | |
|
||||
| | | | * | | |
|
||||
* | | | | | | |
|
||||
| |/ / / / / /
|
||||
|/| / / / / /
|
||||
* | | | | | |
|
||||
|/ / / / / /
|
||||
* | | | | |
|
||||
| | | | | *
|
||||
| | | | |/
|
||||
| | | | *
|
||||
------------
|
@ -28,77 +28,9 @@ and `diff.c` for examples.
|
||||
|
||||
* `struct ll_merge_options`
|
||||
|
||||
This describes the set of options the calling program wants to affect
|
||||
the operation of a low-level (single file) merge. Some options:
|
||||
|
||||
`virtual_ancestor`::
|
||||
Behave as though this were part of a merge between common
|
||||
ancestors in a recursive merge.
|
||||
If a helper program is specified by the
|
||||
`[merge "<driver>"] recursive` configuration, it will
|
||||
be used (see linkgit:gitattributes[5]).
|
||||
|
||||
`variant`::
|
||||
Resolve local conflicts automatically in favor
|
||||
of one side or the other (as in 'git merge-file'
|
||||
`--ours`/`--theirs`/`--union`). Can be `0`,
|
||||
`XDL_MERGE_FAVOR_OURS`, `XDL_MERGE_FAVOR_THEIRS`, or
|
||||
`XDL_MERGE_FAVOR_UNION`.
|
||||
|
||||
`renormalize`::
|
||||
Resmudge and clean the "base", "theirs" and "ours" files
|
||||
before merging. Use this when the merge is likely to have
|
||||
overlapped with a change in smudge/clean or end-of-line
|
||||
normalization rules.
|
||||
Check ll-merge.h for details.
|
||||
|
||||
Low-level (single file) merge
|
||||
-----------------------------
|
||||
|
||||
`ll_merge`::
|
||||
|
||||
Perform a three-way single-file merge in core. This is
|
||||
a thin wrapper around `xdl_merge` that takes the path and
|
||||
any merge backend specified in `.gitattributes` or
|
||||
`.git/info/attributes` into account. Returns 0 for a
|
||||
clean merge.
|
||||
|
||||
Calling sequence:
|
||||
|
||||
* Prepare a `struct ll_merge_options` to record options.
|
||||
If you have no special requests, skip this and pass `NULL`
|
||||
as the `opts` parameter to use the default options.
|
||||
|
||||
* Allocate an mmbuffer_t variable for the result.
|
||||
|
||||
* Allocate and fill variables with the file's original content
|
||||
and two modified versions (using `read_mmfile`, for example).
|
||||
|
||||
* Call `ll_merge()`.
|
||||
|
||||
* Read the merged content from `result_buf.ptr` and `result_buf.size`.
|
||||
|
||||
* Release buffers when finished. A simple
|
||||
`free(ancestor.ptr); free(ours.ptr); free(theirs.ptr);
|
||||
free(result_buf.ptr);` will do.
|
||||
|
||||
If the modifications do not merge cleanly, `ll_merge` will return a
|
||||
nonzero value and `result_buf` will generally include a description of
|
||||
the conflict bracketed by markers such as the traditional `<<<<<<<`
|
||||
and `>>>>>>>`.
|
||||
|
||||
The `ancestor_label`, `our_label`, and `their_label` parameters are
|
||||
used to label the different sides of a conflict if the merge driver
|
||||
supports this.
|
||||
|
||||
Everything else
|
||||
---------------
|
||||
|
||||
Talk about <merge-recursive.h> and merge_file():
|
||||
|
||||
- merge_trees() to merge with rename detection
|
||||
- merge_recursive() for ancestor consolidation
|
||||
- try_merge_command() for other strategies
|
||||
- conflict format
|
||||
- merge options
|
||||
|
||||
(Daniel, Miklos, Stephan, JC)
|
||||
Check ll-merge.h for details.
|
||||
|
@ -1,90 +0,0 @@
|
||||
oid-array API
|
||||
==============
|
||||
|
||||
The oid-array API provides storage and manipulation of sets of object
|
||||
identifiers. The emphasis is on storage and processing efficiency,
|
||||
making them suitable for large lists. Note that the ordering of items is
|
||||
not preserved over some operations.
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct oid_array`::
|
||||
|
||||
A single array of object IDs. This should be initialized by
|
||||
assignment from `OID_ARRAY_INIT`. The `oid` member contains
|
||||
the actual data. The `nr` member contains the number of items in
|
||||
the set. The `alloc` and `sorted` members are used internally,
|
||||
and should not be needed by API callers.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`oid_array_append`::
|
||||
Add an item to the set. The object ID will be placed at the end of
|
||||
the array (but note that some operations below may lose this
|
||||
ordering).
|
||||
|
||||
`oid_array_lookup`::
|
||||
Perform a binary search of the array for a specific object ID.
|
||||
If found, returns the offset (in number of elements) of the
|
||||
object ID. If not found, returns a negative integer. If the array
|
||||
is not sorted, this function has the side effect of sorting it.
|
||||
|
||||
`oid_array_clear`::
|
||||
Free all memory associated with the array and return it to the
|
||||
initial, empty state.
|
||||
|
||||
`oid_array_for_each`::
|
||||
Iterate over each element of the list, executing the callback
|
||||
function for each one. Does not sort the list, so any custom
|
||||
hash order is retained. If the callback returns a non-zero
|
||||
value, the iteration ends immediately and the callback's
|
||||
return is propagated; otherwise, 0 is returned.
|
||||
|
||||
`oid_array_for_each_unique`::
|
||||
Iterate over each unique element of the list in sorted order,
|
||||
but otherwise behave like `oid_array_for_each`. If the array
|
||||
is not sorted, this function has the side effect of sorting
|
||||
it.
|
||||
|
||||
`oid_array_filter`::
|
||||
Apply the callback function `want` to each entry in the array,
|
||||
retaining only the entries for which the function returns true.
|
||||
Preserve the order of the entries that are retained.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
-----------------------------------------
|
||||
int print_callback(const struct object_id *oid,
|
||||
void *data)
|
||||
{
|
||||
printf("%s\n", oid_to_hex(oid));
|
||||
return 0; /* always continue */
|
||||
}
|
||||
|
||||
void some_func(void)
|
||||
{
|
||||
struct sha1_array hashes = OID_ARRAY_INIT;
|
||||
struct object_id oid;
|
||||
|
||||
/* Read objects into our set */
|
||||
while (read_object_from_stdin(oid.hash))
|
||||
oid_array_append(&hashes, &oid);
|
||||
|
||||
/* Check if some objects are in our set */
|
||||
while (read_object_from_stdin(oid.hash)) {
|
||||
if (oid_array_lookup(&hashes, &oid) >= 0)
|
||||
printf("it's in there!\n");
|
||||
|
||||
/*
|
||||
* Print the unique set of objects. We could also have
|
||||
* avoided adding duplicate objects in the first place,
|
||||
* but we would end up re-sorting the array repeatedly.
|
||||
* Instead, this will sort once and then skip duplicates
|
||||
* in linear time.
|
||||
*/
|
||||
oid_array_for_each_unique(&hashes, print_callback, NULL);
|
||||
}
|
||||
-----------------------------------------
|
@ -1,78 +0,0 @@
|
||||
ref iteration API
|
||||
=================
|
||||
|
||||
|
||||
Iteration of refs is done by using an iterate function which will call a
|
||||
callback function for every ref. The callback function has this
|
||||
signature:
|
||||
|
||||
int handle_one_ref(const char *refname, const struct object_id *oid,
|
||||
int flags, void *cb_data);
|
||||
|
||||
There are different kinds of iterate functions which all take a
|
||||
callback of this type. The callback is then called for each found ref
|
||||
until the callback returns nonzero. The returned value is then also
|
||||
returned by the iterate function.
|
||||
|
||||
Iteration functions
|
||||
-------------------
|
||||
|
||||
* `head_ref()` just iterates the head ref.
|
||||
|
||||
* `for_each_ref()` iterates all refs.
|
||||
|
||||
* `for_each_ref_in()` iterates all refs which have a defined prefix and
|
||||
strips that prefix from the passed variable refname.
|
||||
|
||||
* `for_each_tag_ref()`, `for_each_branch_ref()`, `for_each_remote_ref()`,
|
||||
`for_each_replace_ref()` iterate refs from the respective area.
|
||||
|
||||
* `for_each_glob_ref()` iterates all refs that match the specified glob
|
||||
pattern.
|
||||
|
||||
* `for_each_glob_ref_in()` the previous and `for_each_ref_in()` combined.
|
||||
|
||||
* Use `refs_` API for accessing submodules. The submodule ref store could
|
||||
be obtained with `get_submodule_ref_store()`.
|
||||
|
||||
* `for_each_rawref()` can be used to learn about broken ref and symref.
|
||||
|
||||
* `for_each_reflog()` iterates each reflog file.
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
If you want to iterate the refs of a submodule you first need to add the
|
||||
submodules object database. You can do this by a code-snippet like
|
||||
this:
|
||||
|
||||
const char *path = "path/to/submodule"
|
||||
if (add_submodule_odb(path))
|
||||
die("Error submodule '%s' not populated.", path);
|
||||
|
||||
`add_submodule_odb()` will return zero on success. If you
|
||||
do not do this you will get an error for each ref that it does not point
|
||||
to a valid object.
|
||||
|
||||
Note: As a side-effect of this you cannot safely assume that all
|
||||
objects you lookup are available in superproject. All submodule objects
|
||||
will be available the same way as the superprojects objects.
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
----
|
||||
static int handle_remote_ref(const char *refname,
|
||||
const unsigned char *sha1, int flags, void *cb_data)
|
||||
{
|
||||
struct strbuf *output = cb_data;
|
||||
strbuf_addf(output, "%s\n", refname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
struct strbuf output = STRBUF_INIT;
|
||||
for_each_remote_ref(handle_remote_ref, &output);
|
||||
printf("%s", output.buf);
|
||||
----
|
@ -1,127 +0,0 @@
|
||||
Remotes configuration API
|
||||
=========================
|
||||
|
||||
The API in remote.h gives access to the configuration related to
|
||||
remotes. It handles all three configuration mechanisms historically
|
||||
and currently used by Git, and presents the information in a uniform
|
||||
fashion. Note that the code also handles plain URLs without any
|
||||
configuration, giving them just the default information.
|
||||
|
||||
struct remote
|
||||
-------------
|
||||
|
||||
`name`::
|
||||
|
||||
The user's nickname for the remote
|
||||
|
||||
`url`::
|
||||
|
||||
An array of all of the url_nr URLs configured for the remote
|
||||
|
||||
`pushurl`::
|
||||
|
||||
An array of all of the pushurl_nr push URLs configured for the remote
|
||||
|
||||
`push`::
|
||||
|
||||
An array of refspecs configured for pushing, with
|
||||
push_refspec being the literal strings, and push_refspec_nr
|
||||
being the quantity.
|
||||
|
||||
`fetch`::
|
||||
|
||||
An array of refspecs configured for fetching, with
|
||||
fetch_refspec being the literal strings, and fetch_refspec_nr
|
||||
being the quantity.
|
||||
|
||||
`fetch_tags`::
|
||||
|
||||
The setting for whether to fetch tags (as a separate rule from
|
||||
the configured refspecs); -1 means never to fetch tags, 0
|
||||
means to auto-follow tags based on the default heuristic, 1
|
||||
means to always auto-follow tags, and 2 means to fetch all
|
||||
tags.
|
||||
|
||||
`receivepack`, `uploadpack`::
|
||||
|
||||
The configured helper programs to run on the remote side, for
|
||||
Git-native protocols.
|
||||
|
||||
`http_proxy`::
|
||||
|
||||
The proxy to use for curl (http, https, ftp, etc.) URLs.
|
||||
|
||||
`http_proxy_authmethod`::
|
||||
|
||||
The method used for authenticating against `http_proxy`.
|
||||
|
||||
struct remotes can be found by name with remote_get(), and iterated
|
||||
through with for_each_remote(). remote_get(NULL) will return the
|
||||
default remote, given the current branch and configuration.
|
||||
|
||||
struct refspec
|
||||
--------------
|
||||
|
||||
A struct refspec holds the parsed interpretation of a refspec. If it
|
||||
will force updates (starts with a '+'), force is true. If it is a
|
||||
pattern (sides end with '*') pattern is true. src and dest are the
|
||||
two sides (including '*' characters if present); if there is only one
|
||||
side, it is src, and dst is NULL; if sides exist but are empty (i.e.,
|
||||
the refspec either starts or ends with ':'), the corresponding side is
|
||||
"".
|
||||
|
||||
An array of strings can be parsed into an array of struct refspecs
|
||||
using parse_fetch_refspec() or parse_push_refspec().
|
||||
|
||||
remote_find_tracking(), given a remote and a struct refspec with
|
||||
either src or dst filled out, will fill out the other such that the
|
||||
result is in the "fetch" specification for the remote (note that this
|
||||
evaluates patterns and returns a single result).
|
||||
|
||||
struct branch
|
||||
-------------
|
||||
|
||||
Note that this may end up moving to branch.h
|
||||
|
||||
struct branch holds the configuration for a branch. It can be looked
|
||||
up with branch_get(name) for "refs/heads/{name}", or with
|
||||
branch_get(NULL) for HEAD.
|
||||
|
||||
It contains:
|
||||
|
||||
`name`::
|
||||
|
||||
The short name of the branch.
|
||||
|
||||
`refname`::
|
||||
|
||||
The full path for the branch ref.
|
||||
|
||||
`remote_name`::
|
||||
|
||||
The name of the remote listed in the configuration.
|
||||
|
||||
`merge_name`::
|
||||
|
||||
An array of the "merge" lines in the configuration.
|
||||
|
||||
`merge`::
|
||||
|
||||
An array of the struct refspecs used for the merge lines. That
|
||||
is, merge[i]->dst is a local tracking ref which should be
|
||||
merged into this branch by default.
|
||||
|
||||
`merge_nr`::
|
||||
|
||||
The number of merge configurations
|
||||
|
||||
branch_has_merge_config() returns true if the given branch has merge
|
||||
configuration given.
|
||||
|
||||
Other stuff
|
||||
-----------
|
||||
|
||||
There is other stuff in remote.h that is related, in general, to the
|
||||
process of interacting with remotes.
|
||||
|
||||
(Daniel Barkalow)
|
@ -1,72 +0,0 @@
|
||||
revision walking API
|
||||
====================
|
||||
|
||||
The revision walking API offers functions to build a list of revisions
|
||||
and then iterate over that list.
|
||||
|
||||
Calling sequence
|
||||
----------------
|
||||
|
||||
The walking API has a given calling sequence: first you need to
|
||||
initialize a rev_info structure, then add revisions to control what kind
|
||||
of revision list do you want to get, finally you can iterate over the
|
||||
revision list.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`repo_init_revisions`::
|
||||
|
||||
Initialize a rev_info structure with default values. The third
|
||||
parameter may be NULL or can be prefix path, and then the `.prefix`
|
||||
variable will be set to it. This is typically the first function you
|
||||
want to call when you want to deal with a revision list. After calling
|
||||
this function, you are free to customize options, like set
|
||||
`.ignore_merges` to 0 if you don't want to ignore merges, and so on. See
|
||||
`revision.h` for a complete list of available options.
|
||||
|
||||
`add_pending_object`::
|
||||
|
||||
This function can be used if you want to add commit objects as revision
|
||||
information. You can use the `UNINTERESTING` object flag to indicate if
|
||||
you want to include or exclude the given commit (and commits reachable
|
||||
from the given commit) from the revision list.
|
||||
+
|
||||
NOTE: If you have the commits as a string list then you probably want to
|
||||
use setup_revisions(), instead of parsing each string and using this
|
||||
function.
|
||||
|
||||
`setup_revisions`::
|
||||
|
||||
Parse revision information, filling in the `rev_info` structure, and
|
||||
removing the used arguments from the argument list. Returns the number
|
||||
of arguments left that weren't recognized, which are also moved to the
|
||||
head of the argument list. The last parameter is used in case no
|
||||
parameter given by the first two arguments.
|
||||
|
||||
`prepare_revision_walk`::
|
||||
|
||||
Prepares the rev_info structure for a walk. You should check if it
|
||||
returns any error (non-zero return code) and if it does not, you can
|
||||
start using get_revision() to do the iteration.
|
||||
|
||||
`get_revision`::
|
||||
|
||||
Takes a pointer to a `rev_info` structure and iterates over it,
|
||||
returning a `struct commit *` each time you call it. The end of the
|
||||
revision list is indicated by returning a NULL pointer.
|
||||
|
||||
`reset_revision_walk`::
|
||||
|
||||
Reset the flags used by the revision walking api. You can use
|
||||
this to do multiple sequential revision walks.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
Talk about <revision.h>, things like:
|
||||
|
||||
* two diff_options, one for path limiting, another for output;
|
||||
* remaining functions;
|
||||
|
||||
(Linus, JC, Dscho)
|
@ -1,264 +0,0 @@
|
||||
run-command API
|
||||
===============
|
||||
|
||||
The run-command API offers a versatile tool to run sub-processes with
|
||||
redirected input and output as well as with a modified environment
|
||||
and an alternate current directory.
|
||||
|
||||
A similar API offers the capability to run a function asynchronously,
|
||||
which is primarily used to capture the output that the function
|
||||
produces in the caller in order to process it.
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`child_process_init`::
|
||||
|
||||
Initialize a struct child_process variable.
|
||||
|
||||
`start_command`::
|
||||
|
||||
Start a sub-process. Takes a pointer to a `struct child_process`
|
||||
that specifies the details and returns pipe FDs (if requested).
|
||||
See below for details.
|
||||
|
||||
`finish_command`::
|
||||
|
||||
Wait for the completion of a sub-process that was started with
|
||||
start_command().
|
||||
|
||||
`run_command`::
|
||||
|
||||
A convenience function that encapsulates a sequence of
|
||||
start_command() followed by finish_command(). Takes a pointer
|
||||
to a `struct child_process` that specifies the details.
|
||||
|
||||
`run_command_v_opt`, `run_command_v_opt_cd_env`::
|
||||
|
||||
Convenience functions that encapsulate a sequence of
|
||||
start_command() followed by finish_command(). The argument argv
|
||||
specifies the program and its arguments. The argument opt is zero
|
||||
or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`,
|
||||
`RUN_COMMAND_STDOUT_TO_STDERR`, or `RUN_SILENT_EXEC_FAILURE`
|
||||
that correspond to the members .no_stdin, .git_cmd,
|
||||
.stdout_to_stderr, .silent_exec_failure of `struct child_process`.
|
||||
The argument dir corresponds the member .dir. The argument env
|
||||
corresponds to the member .env.
|
||||
|
||||
`child_process_clear`::
|
||||
|
||||
Release the memory associated with the struct child_process.
|
||||
Most users of the run-command API don't need to call this
|
||||
function explicitly because `start_command` invokes it on
|
||||
failure and `finish_command` calls it automatically already.
|
||||
|
||||
The functions above do the following:
|
||||
|
||||
. If a system call failed, errno is set and -1 is returned. A diagnostic
|
||||
is printed.
|
||||
|
||||
. If the program was not found, then -1 is returned and errno is set to
|
||||
ENOENT; a diagnostic is printed only if .silent_exec_failure is 0.
|
||||
|
||||
. Otherwise, the program is run. If it terminates regularly, its exit
|
||||
code is returned. No diagnostic is printed, even if the exit code is
|
||||
non-zero.
|
||||
|
||||
. If the program terminated due to a signal, then the return value is the
|
||||
signal number + 128, ie. the same value that a POSIX shell's $? would
|
||||
report. A diagnostic is printed.
|
||||
|
||||
|
||||
`start_async`::
|
||||
|
||||
Run a function asynchronously. Takes a pointer to a `struct
|
||||
async` that specifies the details and returns a set of pipe FDs
|
||||
for communication with the function. See below for details.
|
||||
|
||||
`finish_async`::
|
||||
|
||||
Wait for the completion of an asynchronous function that was
|
||||
started with start_async().
|
||||
|
||||
`run_hook`::
|
||||
|
||||
Run a hook.
|
||||
The first argument is a pathname to an index file, or NULL
|
||||
if the hook uses the default index file or no index is needed.
|
||||
The second argument is the name of the hook.
|
||||
The further arguments correspond to the hook arguments.
|
||||
The last argument has to be NULL to terminate the arguments list.
|
||||
If the hook does not exist or is not executable, the return
|
||||
value will be zero.
|
||||
If it is executable, the hook will be executed and the exit
|
||||
status of the hook is returned.
|
||||
On execution, .stdout_to_stderr and .no_stdin will be set.
|
||||
(See below.)
|
||||
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
* `struct child_process`
|
||||
|
||||
This describes the arguments, redirections, and environment of a
|
||||
command to run in a sub-process.
|
||||
|
||||
The caller:
|
||||
|
||||
1. allocates and clears (using child_process_init() or
|
||||
CHILD_PROCESS_INIT) a struct child_process variable;
|
||||
2. initializes the members;
|
||||
3. calls start_command();
|
||||
4. processes the data;
|
||||
5. closes file descriptors (if necessary; see below);
|
||||
6. calls finish_command().
|
||||
|
||||
The .argv member is set up as an array of string pointers (NULL
|
||||
terminated), of which .argv[0] is the program name to run (usually
|
||||
without a path). If the command to run is a git command, set argv[0] to
|
||||
the command name without the 'git-' prefix and set .git_cmd = 1.
|
||||
|
||||
Note that the ownership of the memory pointed to by .argv stays with the
|
||||
caller, but it should survive until `finish_command` completes. If the
|
||||
.argv member is NULL, `start_command` will point it at the .args
|
||||
`argv_array` (so you may use one or the other, but you must use exactly
|
||||
one). The memory in .args will be cleaned up automatically during
|
||||
`finish_command` (or during `start_command` when it is unsuccessful).
|
||||
|
||||
The members .in, .out, .err are used to redirect stdin, stdout,
|
||||
stderr as follows:
|
||||
|
||||
. Specify 0 to request no special redirection. No new file descriptor
|
||||
is allocated. The child process simply inherits the channel from the
|
||||
parent.
|
||||
|
||||
. Specify -1 to have a pipe allocated; start_command() replaces -1
|
||||
by the pipe FD in the following way:
|
||||
|
||||
.in: Returns the writable pipe end into which the caller writes;
|
||||
the readable end of the pipe becomes the child's stdin.
|
||||
|
||||
.out, .err: Returns the readable pipe end from which the caller
|
||||
reads; the writable end of the pipe end becomes child's
|
||||
stdout/stderr.
|
||||
|
||||
The caller of start_command() must close the so returned FDs
|
||||
after it has completed reading from/writing to it!
|
||||
|
||||
. Specify a file descriptor > 0 to be used by the child:
|
||||
|
||||
.in: The FD must be readable; it becomes child's stdin.
|
||||
.out: The FD must be writable; it becomes child's stdout.
|
||||
.err: The FD must be writable; it becomes child's stderr.
|
||||
|
||||
The specified FD is closed by start_command(), even if it fails to
|
||||
run the sub-process!
|
||||
|
||||
. Special forms of redirection are available by setting these members
|
||||
to 1:
|
||||
|
||||
.no_stdin, .no_stdout, .no_stderr: The respective channel is
|
||||
redirected to /dev/null.
|
||||
|
||||
.stdout_to_stderr: stdout of the child is redirected to its
|
||||
stderr. This happens after stderr is itself redirected.
|
||||
So stdout will follow stderr to wherever it is
|
||||
redirected.
|
||||
|
||||
To modify the environment of the sub-process, specify an array of
|
||||
string pointers (NULL terminated) in .env:
|
||||
|
||||
. If the string is of the form "VAR=value", i.e. it contains '='
|
||||
the variable is added to the child process's environment.
|
||||
|
||||
. If the string does not contain '=', it names an environment
|
||||
variable that will be removed from the child process's environment.
|
||||
|
||||
If the .env member is NULL, `start_command` will point it at the
|
||||
.env_array `argv_array` (so you may use one or the other, but not both).
|
||||
The memory in .env_array will be cleaned up automatically during
|
||||
`finish_command` (or during `start_command` when it is unsuccessful).
|
||||
|
||||
To specify a new initial working directory for the sub-process,
|
||||
specify it in the .dir member.
|
||||
|
||||
If the program cannot be found, the functions return -1 and set
|
||||
errno to ENOENT. Normally, an error message is printed, but if
|
||||
.silent_exec_failure is set to 1, no message is printed for this
|
||||
special error condition.
|
||||
|
||||
|
||||
* `struct async`
|
||||
|
||||
This describes a function to run asynchronously, whose purpose is
|
||||
to produce output that the caller reads.
|
||||
|
||||
The caller:
|
||||
|
||||
1. allocates and clears (memset(&asy, 0, sizeof(asy));) a
|
||||
struct async variable;
|
||||
2. initializes .proc and .data;
|
||||
3. calls start_async();
|
||||
4. processes communicates with proc through .in and .out;
|
||||
5. closes .in and .out;
|
||||
6. calls finish_async().
|
||||
|
||||
The members .in, .out are used to provide a set of fd's for
|
||||
communication between the caller and the callee as follows:
|
||||
|
||||
. Specify 0 to have no file descriptor passed. The callee will
|
||||
receive -1 in the corresponding argument.
|
||||
|
||||
. Specify < 0 to have a pipe allocated; start_async() replaces
|
||||
with the pipe FD in the following way:
|
||||
|
||||
.in: Returns the writable pipe end into which the caller
|
||||
writes; the readable end of the pipe becomes the function's
|
||||
in argument.
|
||||
|
||||
.out: Returns the readable pipe end from which the caller
|
||||
reads; the writable end of the pipe becomes the function's
|
||||
out argument.
|
||||
|
||||
The caller of start_async() must close the returned FDs after it
|
||||
has completed reading from/writing from them.
|
||||
|
||||
. Specify a file descriptor > 0 to be used by the function:
|
||||
|
||||
.in: The FD must be readable; it becomes the function's in.
|
||||
.out: The FD must be writable; it becomes the function's out.
|
||||
|
||||
The specified FD is closed by start_async(), even if it fails to
|
||||
run the function.
|
||||
|
||||
The function pointer in .proc has the following signature:
|
||||
|
||||
int proc(int in, int out, void *data);
|
||||
|
||||
. in, out specifies a set of file descriptors to which the function
|
||||
must read/write the data that it needs/produces. The function
|
||||
*must* close these descriptors before it returns. A descriptor
|
||||
may be -1 if the caller did not configure a descriptor for that
|
||||
direction.
|
||||
|
||||
. data is the value that the caller has specified in the .data member
|
||||
of struct async.
|
||||
|
||||
. The return value of the function is 0 on success and non-zero
|
||||
on failure. If the function indicates failure, finish_async() will
|
||||
report failure as well.
|
||||
|
||||
|
||||
There are serious restrictions on what the asynchronous function can do
|
||||
because this facility is implemented by a thread in the same address
|
||||
space on most platforms (when pthreads is available), but by a pipe to
|
||||
a forked process otherwise:
|
||||
|
||||
. It cannot change the program's state (global variables, environment,
|
||||
etc.) in a way that the caller notices; in other words, .in and .out
|
||||
are the only communication channels to the caller.
|
||||
|
||||
. It must not change the program's state that the caller of the
|
||||
facility also uses.
|
@ -1,47 +0,0 @@
|
||||
setup API
|
||||
=========
|
||||
|
||||
Talk about
|
||||
|
||||
* setup_git_directory()
|
||||
* setup_git_directory_gently()
|
||||
* is_inside_git_dir()
|
||||
* is_inside_work_tree()
|
||||
* setup_work_tree()
|
||||
|
||||
(Dscho)
|
||||
|
||||
Pathspec
|
||||
--------
|
||||
|
||||
See glossary-context.txt for the syntax of pathspec. In memory, a
|
||||
pathspec set is represented by "struct pathspec" and is prepared by
|
||||
parse_pathspec(). This function takes several arguments:
|
||||
|
||||
- magic_mask specifies what features that are NOT supported by the
|
||||
following code. If a user attempts to use such a feature,
|
||||
parse_pathspec() can reject it early.
|
||||
|
||||
- flags specifies other things that the caller wants parse_pathspec to
|
||||
perform.
|
||||
|
||||
- prefix and args come from cmd_* functions
|
||||
|
||||
parse_pathspec() helps catch unsupported features and reject them
|
||||
politely. At a lower level, different pathspec-related functions may
|
||||
not support the same set of features. Such pathspec-sensitive
|
||||
functions are guarded with GUARD_PATHSPEC(), which will die in an
|
||||
unfriendly way when an unsupported feature is requested.
|
||||
|
||||
The command designers are supposed to make sure that GUARD_PATHSPEC()
|
||||
never dies. They have to make sure all unsupported features are caught
|
||||
by parse_pathspec(), not by GUARD_PATHSPEC. grepping GUARD_PATHSPEC()
|
||||
should give the designers all pathspec-sensitive codepaths and what
|
||||
features they support.
|
||||
|
||||
A similar process is applied when a new pathspec magic is added. The
|
||||
designer lifts the GUARD_PATHSPEC restriction in the functions that
|
||||
support the new magic. At the same time (s)he has to make sure this
|
||||
new feature will be caught at parse_pathspec() in commands that cannot
|
||||
handle the new magic in some cases. grepping parse_pathspec() should
|
||||
help.
|
@ -1,41 +0,0 @@
|
||||
sigchain API
|
||||
============
|
||||
|
||||
Code often wants to set a signal handler to clean up temporary files or
|
||||
other work-in-progress when we die unexpectedly. For multiple pieces of
|
||||
code to do this without conflicting, each piece of code must remember
|
||||
the old value of the handler and restore it either when:
|
||||
|
||||
1. The work-in-progress is finished, and the handler is no longer
|
||||
necessary. The handler should revert to the original behavior
|
||||
(either another handler, SIG_DFL, or SIG_IGN).
|
||||
|
||||
2. The signal is received. We should then do our cleanup, then chain
|
||||
to the next handler (or die if it is SIG_DFL).
|
||||
|
||||
Sigchain is a tiny library for keeping a stack of handlers. Your handler
|
||||
and installation code should look something like:
|
||||
|
||||
------------------------------------------
|
||||
void clean_foo_on_signal(int sig)
|
||||
{
|
||||
clean_foo();
|
||||
sigchain_pop(sig);
|
||||
raise(sig);
|
||||
}
|
||||
|
||||
void other_func()
|
||||
{
|
||||
sigchain_push_common(clean_foo_on_signal);
|
||||
mess_up_foo();
|
||||
clean_foo();
|
||||
}
|
||||
------------------------------------------
|
||||
|
||||
Handlers are given the typedef of sigchain_fun. This is the same type
|
||||
that is given to signal() or sigaction(). It is perfectly reasonable to
|
||||
push SIG_DFL or SIG_IGN onto the stack.
|
||||
|
||||
You can sigchain_push and sigchain_pop individual signals. For
|
||||
convenience, sigchain_push_common will push the handler onto the stack
|
||||
for many common signals.
|
@ -1,66 +0,0 @@
|
||||
submodule config cache API
|
||||
==========================
|
||||
|
||||
The submodule config cache API allows to read submodule
|
||||
configurations/information from specified revisions. Internally
|
||||
information is lazily read into a cache that is used to avoid
|
||||
unnecessary parsing of the same .gitmodules files. Lookups can be done by
|
||||
submodule path or name.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To initialize the cache with configurations from the worktree the caller
|
||||
typically first calls `gitmodules_config()` to read values from the
|
||||
worktree .gitmodules and then to overlay the local git config values
|
||||
`parse_submodule_config_option()` from the config parsing
|
||||
infrastructure.
|
||||
|
||||
The caller can look up information about submodules by using the
|
||||
`submodule_from_path()` or `submodule_from_name()` functions. They return
|
||||
a `struct submodule` which contains the values. The API automatically
|
||||
initializes and allocates the needed infrastructure on-demand. If the
|
||||
caller does only want to lookup values from revisions the initialization
|
||||
can be skipped.
|
||||
|
||||
If the internal cache might grow too big or when the caller is done with
|
||||
the API, all internally cached values can be freed with submodule_free().
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct submodule`::
|
||||
|
||||
This structure is used to return the information about one
|
||||
submodule for a certain revision. It is returned by the lookup
|
||||
functions.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`void submodule_free(struct repository *r)`::
|
||||
|
||||
Use these to free the internally cached values.
|
||||
|
||||
`int parse_submodule_config_option(const char *var, const char *value)`::
|
||||
|
||||
Can be passed to the config parsing infrastructure to parse
|
||||
local (worktree) submodule configurations.
|
||||
|
||||
`const struct submodule *submodule_from_path(const unsigned char *treeish_name, const char *path)`::
|
||||
|
||||
Given a tree-ish in the superproject and a path, return the
|
||||
submodule that is bound at the path in the named tree.
|
||||
|
||||
`const struct submodule *submodule_from_name(const unsigned char *treeish_name, const char *name)`::
|
||||
|
||||
The same as above but lookup by name.
|
||||
|
||||
Whenever a submodule configuration is parsed in `parse_submodule_config_option`
|
||||
via e.g. `gitmodules_config()`, it will overwrite the null_sha1 entry.
|
||||
So in the normal case, when HEAD:.gitmodules is parsed first and then overlaid
|
||||
with the repository configuration, the null_sha1 entry contains the local
|
||||
configuration of a submodule (e.g. consolidated values from local git
|
||||
configuration and the .gitmodules file in the worktree).
|
||||
|
||||
For an example usage see test-submodule-config.c.
|
@ -1,140 +0,0 @@
|
||||
trace API
|
||||
=========
|
||||
|
||||
The trace API can be used to print debug messages to stderr or a file. Trace
|
||||
code is inactive unless explicitly enabled by setting `GIT_TRACE*` environment
|
||||
variables.
|
||||
|
||||
The trace implementation automatically adds `timestamp file:line ... \n` to
|
||||
all trace messages. E.g.:
|
||||
|
||||
------------
|
||||
23:59:59.123456 git.c:312 trace: built-in: git 'foo'
|
||||
00:00:00.000001 builtin/foo.c:99 foo: some message
|
||||
------------
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct trace_key`::
|
||||
|
||||
Defines a trace key (or category). The default (for API functions that
|
||||
don't take a key) is `GIT_TRACE`.
|
||||
+
|
||||
E.g. to define a trace key controlled by environment variable `GIT_TRACE_FOO`:
|
||||
+
|
||||
------------
|
||||
static struct trace_key trace_foo = TRACE_KEY_INIT(FOO);
|
||||
|
||||
static void trace_print_foo(const char *message)
|
||||
{
|
||||
trace_printf_key(&trace_foo, "%s", message);
|
||||
}
|
||||
------------
|
||||
+
|
||||
Note: don't use `const` as the trace implementation stores internal state in
|
||||
the `trace_key` structure.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`int trace_want(struct trace_key *key)`::
|
||||
|
||||
Checks whether the trace key is enabled. Used to prevent expensive
|
||||
string formatting before calling one of the printing APIs.
|
||||
|
||||
`void trace_disable(struct trace_key *key)`::
|
||||
|
||||
Disables tracing for the specified key, even if the environment
|
||||
variable was set.
|
||||
|
||||
`void trace_printf(const char *format, ...)`::
|
||||
`void trace_printf_key(struct trace_key *key, const char *format, ...)`::
|
||||
|
||||
Prints a formatted message, similar to printf.
|
||||
|
||||
`void trace_argv_printf(const char **argv, const char *format, ...)``::
|
||||
|
||||
Prints a formatted message, followed by a quoted list of arguments.
|
||||
|
||||
`void trace_strbuf(struct trace_key *key, const struct strbuf *data)`::
|
||||
|
||||
Prints the strbuf, without additional formatting (i.e. doesn't
|
||||
choke on `%` or even `\0`).
|
||||
|
||||
`uint64_t getnanotime(void)`::
|
||||
|
||||
Returns nanoseconds since the epoch (01/01/1970), typically used
|
||||
for performance measurements.
|
||||
+
|
||||
Currently there are high precision timer implementations for Linux (using
|
||||
`clock_gettime(CLOCK_MONOTONIC)`) and Windows (`QueryPerformanceCounter`).
|
||||
Other platforms use `gettimeofday` as time source.
|
||||
|
||||
`void trace_performance(uint64_t nanos, const char *format, ...)`::
|
||||
`void trace_performance_since(uint64_t start, const char *format, ...)`::
|
||||
|
||||
Prints the elapsed time (in nanoseconds), or elapsed time since
|
||||
`start`, followed by a formatted message. Enabled via environment
|
||||
variable `GIT_TRACE_PERFORMANCE`. Used for manual profiling, e.g.:
|
||||
+
|
||||
------------
|
||||
uint64_t start = getnanotime();
|
||||
/* code section to measure */
|
||||
trace_performance_since(start, "foobar");
|
||||
------------
|
||||
+
|
||||
------------
|
||||
uint64_t t = 0;
|
||||
for (;;) {
|
||||
/* ignore */
|
||||
t -= getnanotime();
|
||||
/* code section to measure */
|
||||
t += getnanotime();
|
||||
/* ignore */
|
||||
}
|
||||
trace_performance(t, "frotz");
|
||||
------------
|
||||
|
||||
Bugs & Caveats
|
||||
--------------
|
||||
|
||||
GIT_TRACE_* environment variables can be used to tell Git to show
|
||||
trace output to its standard error stream. Git can often spawn a pager
|
||||
internally to run its subcommand and send its standard output and
|
||||
standard error to it.
|
||||
|
||||
Because GIT_TRACE_PERFORMANCE trace is generated only at the very end
|
||||
of the program with atexit(), which happens after the pager exits, it
|
||||
would not work well if you send its log to the standard error output
|
||||
and let Git spawn the pager at the same time.
|
||||
|
||||
As a work around, you can for example use '--no-pager', or set
|
||||
GIT_TRACE_PERFORMANCE to another file descriptor which is redirected
|
||||
to stderr, or set GIT_TRACE_PERFORMANCE to a file specified by its
|
||||
absolute path.
|
||||
|
||||
For example instead of the following command which by default may not
|
||||
print any performance information:
|
||||
|
||||
------------
|
||||
GIT_TRACE_PERFORMANCE=2 git log -1
|
||||
------------
|
||||
|
||||
you may want to use:
|
||||
|
||||
------------
|
||||
GIT_TRACE_PERFORMANCE=2 git --no-pager log -1
|
||||
------------
|
||||
|
||||
or:
|
||||
|
||||
------------
|
||||
GIT_TRACE_PERFORMANCE=3 3>&2 git log -1
|
||||
------------
|
||||
|
||||
or:
|
||||
|
||||
------------
|
||||
GIT_TRACE_PERFORMANCE=/path/to/log/file git log -1
|
||||
------------
|
@ -188,261 +188,36 @@ purposes.
|
||||
=== Basic Command Messages
|
||||
|
||||
These are concerned with the lifetime of the overall git process.
|
||||
|
||||
`void trace2_initialize_clock()`::
|
||||
|
||||
Initialize the Trace2 start clock and nothing else. This should
|
||||
be called at the very top of main() to capture the process start
|
||||
time and reduce startup order dependencies.
|
||||
|
||||
`void trace2_initialize()`::
|
||||
|
||||
Determines if any Trace2 Targets should be enabled and
|
||||
initializes the Trace2 facility. This includes setting up the
|
||||
Trace2 thread local storage (TLS).
|
||||
+
|
||||
This function emits a "version" message containing the version of git
|
||||
and the Trace2 protocol.
|
||||
+
|
||||
This function should be called from `main()` as early as possible in
|
||||
the life of the process after essential process initialization.
|
||||
|
||||
`int trace2_is_enabled()`::
|
||||
|
||||
Returns 1 if Trace2 is enabled (at least one target is
|
||||
active).
|
||||
|
||||
`void trace2_cmd_start(int argc, const char **argv)`::
|
||||
|
||||
Emits a "start" message containing the process command line
|
||||
arguments.
|
||||
|
||||
`int trace2_cmd_exit(int exit_code)`::
|
||||
|
||||
Emits an "exit" message containing the process exit-code and
|
||||
elapsed time.
|
||||
+
|
||||
Returns the exit-code.
|
||||
|
||||
`void trace2_cmd_error(const char *fmt, va_list ap)`::
|
||||
|
||||
Emits an "error" message containing a formatted error message.
|
||||
|
||||
`void trace2_cmd_path(const char *pathname)`::
|
||||
|
||||
Emits a "cmd_path" message with the full pathname of the
|
||||
current process.
|
||||
e.g: `void trace2_initialize_clock()`, `void trace2_initialize()`,
|
||||
`int trace2_is_enabled()`, `void trace2_cmd_start(int argc, const char **argv)`.
|
||||
|
||||
=== Command Detail Messages
|
||||
|
||||
These are concerned with describing the specific Git command
|
||||
after the command line, config, and environment are inspected.
|
||||
|
||||
`void trace2_cmd_name(const char *name)`::
|
||||
|
||||
Emits a "cmd_name" message with the canonical name of the
|
||||
command, for example "status" or "checkout".
|
||||
|
||||
`void trace2_cmd_mode(const char *mode)`::
|
||||
|
||||
Emits a "cmd_mode" message with a qualifier name to further
|
||||
describe the current git command.
|
||||
+
|
||||
This message is intended to be used with git commands having multiple
|
||||
major modes. For example, a "checkout" command can checkout a new
|
||||
branch or it can checkout a single file, so the checkout code could
|
||||
emit a cmd_mode message of "branch" or "file".
|
||||
|
||||
`void trace2_cmd_alias(const char *alias, const char **argv_expansion)`::
|
||||
|
||||
Emits an "alias" message containing the alias used and the
|
||||
argument expansion.
|
||||
|
||||
`void trace2_def_param(const char *parameter, const char *value)`::
|
||||
|
||||
Emits a "def_param" message containing a key/value pair.
|
||||
+
|
||||
This message is intended to report some global aspect of the current
|
||||
command, such as a configuration setting or command line switch that
|
||||
significantly affects program performance or behavior, such as
|
||||
`core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`.
|
||||
|
||||
`void trace2_cmd_list_config()`::
|
||||
|
||||
Emits a "def_param" messages for "important" configuration
|
||||
settings.
|
||||
+
|
||||
The environment variable `GIT_TRACE2_CONFIG_PARAMS` or the `trace2.configParams`
|
||||
config value can be set to a
|
||||
list of patterns of important configuration settings, for example:
|
||||
`core.*,remote.*.url`. This function will iterate over all config
|
||||
settings and emit a "def_param" message for each match.
|
||||
|
||||
`void trace2_cmd_set_config(const char *key, const char *value)`::
|
||||
|
||||
Emits a "def_param" message for a new or updated key/value
|
||||
pair IF `key` is considered important.
|
||||
+
|
||||
This is used to hook into `git_config_set()` and catch any
|
||||
configuration changes and update a value previously reported by
|
||||
`trace2_cmd_list_config()`.
|
||||
|
||||
`void trace2_def_repo(struct repository *repo)`::
|
||||
|
||||
Registers a repository with the Trace2 layer. Assigns a
|
||||
unique "repo-id" to `repo->trace2_repo_id`.
|
||||
+
|
||||
Emits a "worktree" messages containing the repo-id and the worktree
|
||||
pathname.
|
||||
+
|
||||
Region and data messages (described later) may refer to this repo-id.
|
||||
+
|
||||
The main/top-level repository will have repo-id value 1 (aka "r1").
|
||||
+
|
||||
The repo-id field is in anticipation of future in-proc submodule
|
||||
repositories.
|
||||
e.g: `void trace2_cmd_name(const char *name)`,
|
||||
`void trace2_cmd_mode(const char *mode)`.
|
||||
|
||||
=== Child Process Messages
|
||||
|
||||
These are concerned with the various spawned child processes,
|
||||
including shell scripts, git commands, editors, pagers, and hooks.
|
||||
|
||||
`void trace2_child_start(struct child_process *cmd)`::
|
||||
|
||||
Emits a "child_start" message containing the "child-id",
|
||||
"child-argv", and "child-classification".
|
||||
+
|
||||
Before calling this, set `cmd->trace2_child_class` to a name
|
||||
describing the type of child process, for example "editor".
|
||||
+
|
||||
This function assigns a unique "child-id" to `cmd->trace2_child_id`.
|
||||
This field is used later during the "child_exit" message to associate
|
||||
it with the "child_start" message.
|
||||
+
|
||||
This function should be called before spawning the child process.
|
||||
|
||||
`void trace2_child_exit(struct child_proess *cmd, int child_exit_code)`::
|
||||
|
||||
Emits a "child_exit" message containing the "child-id",
|
||||
the child's elapsed time and exit-code.
|
||||
+
|
||||
The reported elapsed time includes the process creation overhead and
|
||||
time spend waiting for it to exit, so it may be slightly longer than
|
||||
the time reported by the child itself.
|
||||
+
|
||||
This function should be called after reaping the child process.
|
||||
|
||||
`int trace2_exec(const char *exe, const char **argv)`::
|
||||
|
||||
Emits a "exec" message containing the "exec-id" and the
|
||||
argv of the new process.
|
||||
+
|
||||
This function should be called before calling one of the `exec()`
|
||||
variants, such as `execvp()`.
|
||||
+
|
||||
This function returns a unique "exec-id". This value is used later
|
||||
if the exec() fails and a "exec-result" message is necessary.
|
||||
|
||||
`void trace2_exec_result(int exec_id, int error_code)`::
|
||||
|
||||
Emits a "exec_result" message containing the "exec-id"
|
||||
and the error code.
|
||||
+
|
||||
On Unix-based systems, `exec()` does not return if successful.
|
||||
This message is used to indicate that the `exec()` failed and
|
||||
that the current program is continuing.
|
||||
e.g: `void trace2_child_start(struct child_process *cmd)`.
|
||||
|
||||
=== Git Thread Messages
|
||||
|
||||
These messages are concerned with Git thread usage.
|
||||
|
||||
`void trace2_thread_start(const char *thread_name)`::
|
||||
|
||||
Emits a "thread_start" message.
|
||||
+
|
||||
The `thread_name` field should be a descriptive name, such as the
|
||||
unique name of the thread-proc. A unique "thread-id" will be added
|
||||
to the name to uniquely identify thread instances.
|
||||
+
|
||||
Region and data messages (described later) may refer to this thread
|
||||
name.
|
||||
+
|
||||
This function must be called by the thread-proc of the new thread
|
||||
(so that TLS data is properly initialized) and not by the caller
|
||||
of `pthread_create()`.
|
||||
|
||||
`void trace2_thread_exit()`::
|
||||
|
||||
Emits a "thread_exit" message containing the thread name
|
||||
and the thread elapsed time.
|
||||
+
|
||||
This function must be called by the thread-proc before it returns
|
||||
(so that the correct TLS data is used and cleaned up). It should
|
||||
not be called by the caller of `pthread_join()`.
|
||||
e.g: `void trace2_thread_start(const char *thread_name)`.
|
||||
|
||||
=== Region and Data Messages
|
||||
|
||||
These are concerned with recording performance data
|
||||
over regions or spans of code.
|
||||
over regions or spans of code. e.g:
|
||||
`void trace2_region_enter(const char *category, const char *label, const struct repository *repo)`.
|
||||
|
||||
`void trace2_region_enter(const char *category, const char *label, const struct repository *repo)`::
|
||||
|
||||
`void trace2_region_enter_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`::
|
||||
|
||||
`void trace2_region_enter_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`::
|
||||
|
||||
Emits a thread-relative "region_enter" message with optional
|
||||
printf string.
|
||||
+
|
||||
This function pushes a new region nesting stack level on the current
|
||||
thread and starts a clock for the new stack frame.
|
||||
+
|
||||
The `category` field is an arbitrary category name used to classify
|
||||
regions by feature area, such as "status" or "index". At this time
|
||||
it is only just printed along with the rest of the message. It may
|
||||
be used in the future to filter messages.
|
||||
+
|
||||
The `label` field is an arbitrary label used to describe the activity
|
||||
being started, such as "read_recursive" or "do_read_index".
|
||||
+
|
||||
The `repo` field, if set, will be used to get the "repo-id", so that
|
||||
recursive operations can be attributed to the correct repository.
|
||||
|
||||
`void trace2_region_leave(const char *category, const char *label, const struct repository *repo)`::
|
||||
|
||||
`void trace2_region_leave_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`::
|
||||
|
||||
`void trace2_region_leave_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`::
|
||||
|
||||
Emits a thread-relative "region_leave" message with optional
|
||||
printf string.
|
||||
+
|
||||
This function pops the region nesting stack on the current thread
|
||||
and reports the elapsed time of the stack frame.
|
||||
+
|
||||
The `category`, `label`, and `repo` fields are the same as above.
|
||||
The `category` and `label` do not need to match the corresponding
|
||||
"region_enter" message, but it makes the data stream easier to
|
||||
understand.
|
||||
|
||||
`void trace2_data_string(const char *category, const struct repository *repo, const char *key, const char * value)`::
|
||||
|
||||
`void trace2_data_intmax(const char *category, const struct repository *repo, const char *key, intmax value)`::
|
||||
|
||||
`void trace2_data_json(const char *category, const struct repository *repo, const char *key, const struct json_writer *jw)`::
|
||||
|
||||
Emits a region- and thread-relative "data" or "data_json" message.
|
||||
+
|
||||
This is a key/value pair message containing information about the
|
||||
current thread, region stack, and repository. This could be used
|
||||
to print the number of files in a directory during a multi-threaded
|
||||
recursive tree walk.
|
||||
|
||||
`void trace2_printf(const char *fmt, ...)`::
|
||||
|
||||
`void trace2_printf_va(const char *fmt, va_list ap)`::
|
||||
|
||||
Emits a region- and thread-relative "printf" message.
|
||||
Refer to trace2.h for details about all trace2 functions.
|
||||
|
||||
== Trace2 Target Formats
|
||||
|
||||
|
@ -1,149 +0,0 @@
|
||||
tree walking API
|
||||
================
|
||||
|
||||
The tree walking API is used to traverse and inspect trees.
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct name_entry`::
|
||||
|
||||
An entry in a tree. Each entry has a sha1 identifier, pathname, and
|
||||
mode.
|
||||
|
||||
`struct tree_desc`::
|
||||
|
||||
A semi-opaque data structure used to maintain the current state of the
|
||||
walk.
|
||||
+
|
||||
* `buffer` is a pointer into the memory representation of the tree. It always
|
||||
points at the current entry being visited.
|
||||
|
||||
* `size` counts the number of bytes left in the `buffer`.
|
||||
|
||||
* `entry` points to the current entry being visited.
|
||||
|
||||
`struct traverse_info`::
|
||||
|
||||
A structure used to maintain the state of a traversal.
|
||||
+
|
||||
* `prev` points to the traverse_info which was used to descend into the
|
||||
current tree. If this is the top-level tree `prev` will point to
|
||||
a dummy traverse_info.
|
||||
|
||||
* `name` is the entry for the current tree (if the tree is a subtree).
|
||||
|
||||
* `pathlen` is the length of the full path for the current tree.
|
||||
|
||||
* `conflicts` can be used by callbacks to maintain directory-file conflicts.
|
||||
|
||||
* `fn` is a callback called for each entry in the tree. See Traversing for more
|
||||
information.
|
||||
|
||||
* `data` can be anything the `fn` callback would want to use.
|
||||
|
||||
* `show_all_errors` tells whether to stop at the first error or not.
|
||||
|
||||
Initializing
|
||||
------------
|
||||
|
||||
`init_tree_desc`::
|
||||
|
||||
Initialize a `tree_desc` and decode its first entry. The buffer and
|
||||
size parameters are assumed to be the same as the buffer and size
|
||||
members of `struct tree`.
|
||||
|
||||
`fill_tree_descriptor`::
|
||||
|
||||
Initialize a `tree_desc` and decode its first entry given the
|
||||
object ID of a tree. Returns the `buffer` member if the latter
|
||||
is a valid tree identifier and NULL otherwise.
|
||||
|
||||
`setup_traverse_info`::
|
||||
|
||||
Initialize a `traverse_info` given the pathname of the tree to start
|
||||
traversing from.
|
||||
|
||||
Walking
|
||||
-------
|
||||
|
||||
`tree_entry`::
|
||||
|
||||
Visit the next entry in a tree. Returns 1 when there are more entries
|
||||
left to visit and 0 when all entries have been visited. This is
|
||||
commonly used in the test of a while loop.
|
||||
|
||||
`tree_entry_len`::
|
||||
|
||||
Calculate the length of a tree entry's pathname. This utilizes the
|
||||
memory structure of a tree entry to avoid the overhead of using a
|
||||
generic strlen().
|
||||
|
||||
`update_tree_entry`::
|
||||
|
||||
Walk to the next entry in a tree. This is commonly used in conjunction
|
||||
with `tree_entry_extract` to inspect the current entry.
|
||||
|
||||
`tree_entry_extract`::
|
||||
|
||||
Decode the entry currently being visited (the one pointed to by
|
||||
`tree_desc's` `entry` member) and return the sha1 of the entry. The
|
||||
`pathp` and `modep` arguments are set to the entry's pathname and mode
|
||||
respectively.
|
||||
|
||||
`get_tree_entry`::
|
||||
|
||||
Find an entry in a tree given a pathname and the sha1 of a tree to
|
||||
search. Returns 0 if the entry is found and -1 otherwise. The third
|
||||
and fourth parameters are set to the entry's sha1 and mode
|
||||
respectively.
|
||||
|
||||
Traversing
|
||||
----------
|
||||
|
||||
`traverse_trees`::
|
||||
|
||||
Traverse `n` number of trees in parallel. The `fn` callback member of
|
||||
`traverse_info` is called once for each tree entry.
|
||||
|
||||
`traverse_callback_t`::
|
||||
The arguments passed to the traverse callback are as follows:
|
||||
+
|
||||
* `n` counts the number of trees being traversed.
|
||||
|
||||
* `mask` has its nth bit set if something exists in the nth entry.
|
||||
|
||||
* `dirmask` has its nth bit set if the nth tree's entry is a directory.
|
||||
|
||||
* `entry` is an array of size `n` where the nth entry is from the nth tree.
|
||||
|
||||
* `info` maintains the state of the traversal.
|
||||
|
||||
+
|
||||
Returning a negative value will terminate the traversal. Otherwise the
|
||||
return value is treated as an update mask. If the nth bit is set the nth tree
|
||||
will be updated and if the bit is not set the nth tree entry will be the
|
||||
same in the next callback invocation.
|
||||
|
||||
`make_traverse_path`::
|
||||
|
||||
Generate the full pathname of a tree entry based from the root of the
|
||||
traversal. For example, if the traversal has recursed into another
|
||||
tree named "bar" the pathname of an entry "baz" in the "bar"
|
||||
tree would be "bar/baz".
|
||||
|
||||
`traverse_path_len`::
|
||||
|
||||
Calculate the length of a pathname returned by `make_traverse_path`.
|
||||
This utilizes the memory structure of a tree entry to avoid the
|
||||
overhead of using a generic strlen().
|
||||
|
||||
`strbuf_make_traverse_path`::
|
||||
|
||||
Convenience wrapper to `make_traverse_path` into a strbuf.
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds
|
||||
<torvalds@linux-foundation.org>
|
62
argv-array.h
62
argv-array.h
@ -1,8 +1,32 @@
|
||||
#ifndef ARGV_ARRAY_H
|
||||
#define ARGV_ARRAY_H
|
||||
|
||||
/**
|
||||
* The argv-array API allows one to dynamically build and store
|
||||
* NULL-terminated lists. An argv-array maintains the invariant that the
|
||||
* `argv` member always points to a non-NULL array, and that the array is
|
||||
* always NULL-terminated at the element pointed to by `argv[argc]`. This
|
||||
* makes the result suitable for passing to functions expecting to receive
|
||||
* argv from main().
|
||||
*
|
||||
* The string-list API (documented in string-list.h) is similar, but cannot be
|
||||
* used for these purposes; instead of storing a straight string pointer,
|
||||
* it contains an item structure with a `util` field that is not compatible
|
||||
* with the traditional argv interface.
|
||||
*
|
||||
* Each `argv_array` manages its own memory. Any strings pushed into the
|
||||
* array are duplicated, and all memory is freed by argv_array_clear().
|
||||
*/
|
||||
|
||||
extern const char *empty_argv[];
|
||||
|
||||
/**
|
||||
* A single array. This should be initialized by assignment from
|
||||
* `ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv`
|
||||
* member contains the actual array; the `argc` member contains the
|
||||
* number of elements in the array, not including the terminating
|
||||
* NULL.
|
||||
*/
|
||||
struct argv_array {
|
||||
const char **argv;
|
||||
int argc;
|
||||
@ -11,17 +35,55 @@ struct argv_array {
|
||||
|
||||
#define ARGV_ARRAY_INIT { empty_argv, 0, 0 }
|
||||
|
||||
/**
|
||||
* Initialize an array. This is no different than assigning from
|
||||
* `ARGV_ARRAY_INIT`.
|
||||
*/
|
||||
void argv_array_init(struct argv_array *);
|
||||
|
||||
/* Push a copy of a string onto the end of the array. */
|
||||
const char *argv_array_push(struct argv_array *, const char *);
|
||||
|
||||
/**
|
||||
* Format a string and push it onto the end of the array. This is a
|
||||
* convenience wrapper combining `strbuf_addf` and `argv_array_push`.
|
||||
*/
|
||||
__attribute__((format (printf,2,3)))
|
||||
const char *argv_array_pushf(struct argv_array *, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Push a list of strings onto the end of the array. The arguments
|
||||
* should be a list of `const char *` strings, terminated by a NULL
|
||||
* argument.
|
||||
*/
|
||||
LAST_ARG_MUST_BE_NULL
|
||||
void argv_array_pushl(struct argv_array *, ...);
|
||||
|
||||
/* Push a null-terminated array of strings onto the end of the array. */
|
||||
void argv_array_pushv(struct argv_array *, const char **);
|
||||
|
||||
/**
|
||||
* Remove the final element from the array. If there are no
|
||||
* elements in the array, do nothing.
|
||||
*/
|
||||
void argv_array_pop(struct argv_array *);
|
||||
|
||||
/* Splits by whitespace; does not handle quoted arguments! */
|
||||
void argv_array_split(struct argv_array *, const char *);
|
||||
|
||||
/**
|
||||
* Free all memory associated with the array and return it to the
|
||||
* initial, empty state.
|
||||
*/
|
||||
void argv_array_clear(struct argv_array *);
|
||||
|
||||
/**
|
||||
* Disconnect the `argv` member from the `argv_array` struct and
|
||||
* return it. The caller is responsible for freeing the memory used
|
||||
* by the array, and by the strings it references. After detaching,
|
||||
* the `argv_array` is in a reinitialized state and can be pushed
|
||||
* into again.
|
||||
*/
|
||||
const char **argv_array_detach(struct argv_array *);
|
||||
|
||||
#endif /* ARGV_ARRAY_H */
|
||||
|
3
attr.c
3
attr.c
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Handle git attributes. See gitattributes(5) for a description of
|
||||
* the file syntax, and Documentation/technical/api-gitattributes.txt
|
||||
* for a description of the API.
|
||||
* the file syntax, and attr.h for a description of the API.
|
||||
*
|
||||
* One basic design decision here is that we are not going to support
|
||||
* an insanely large number of attributes.
|
||||
|
141
attr.h
141
attr.h
@ -1,9 +1,121 @@
|
||||
#ifndef ATTR_H
|
||||
#define ATTR_H
|
||||
|
||||
/**
|
||||
* gitattributes mechanism gives a uniform way to associate various attributes
|
||||
* to set of paths.
|
||||
*
|
||||
*
|
||||
* Querying Specific Attributes
|
||||
* ----------------------------
|
||||
*
|
||||
* - Prepare `struct attr_check` using attr_check_initl() function, enumerating
|
||||
* the names of attributes whose values you are interested in, terminated with
|
||||
* a NULL pointer. Alternatively, an empty `struct attr_check` can be
|
||||
* prepared by calling `attr_check_alloc()` function and then attributes you
|
||||
* want to ask about can be added to it with `attr_check_append()` function.
|
||||
*
|
||||
* - Call `git_check_attr()` to check the attributes for the path.
|
||||
*
|
||||
* - Inspect `attr_check` structure to see how each of the attribute in the
|
||||
* array is defined for the path.
|
||||
*
|
||||
*
|
||||
* Example
|
||||
* -------
|
||||
*
|
||||
* To see how attributes "crlf" and "ident" are set for different paths.
|
||||
*
|
||||
* - Prepare a `struct attr_check` with two elements (because we are checking
|
||||
* two attributes):
|
||||
*
|
||||
* ------------
|
||||
* static struct attr_check *check;
|
||||
* static void setup_check(void)
|
||||
* {
|
||||
* if (check)
|
||||
* return; // already done
|
||||
* check = attr_check_initl("crlf", "ident", NULL);
|
||||
* }
|
||||
* ------------
|
||||
*
|
||||
* - Call `git_check_attr()` with the prepared `struct attr_check`:
|
||||
*
|
||||
* ------------
|
||||
* const char *path;
|
||||
*
|
||||
* setup_check();
|
||||
* git_check_attr(path, check);
|
||||
* ------------
|
||||
*
|
||||
* - Act on `.value` member of the result, left in `check->items[]`:
|
||||
*
|
||||
* ------------
|
||||
* const char *value = check->items[0].value;
|
||||
*
|
||||
* if (ATTR_TRUE(value)) {
|
||||
* The attribute is Set, by listing only the name of the
|
||||
* attribute in the gitattributes file for the path.
|
||||
* } else if (ATTR_FALSE(value)) {
|
||||
* The attribute is Unset, by listing the name of the
|
||||
* attribute prefixed with a dash - for the path.
|
||||
* } else if (ATTR_UNSET(value)) {
|
||||
* The attribute is neither set nor unset for the path.
|
||||
* } else if (!strcmp(value, "input")) {
|
||||
* If none of ATTR_TRUE(), ATTR_FALSE(), or ATTR_UNSET() is
|
||||
* true, the value is a string set in the gitattributes
|
||||
* file for the path by saying "attr=value".
|
||||
* } else if (... other check using value as string ...) {
|
||||
* ...
|
||||
* }
|
||||
* ------------
|
||||
*
|
||||
* To see how attributes in argv[] are set for different paths, only
|
||||
* the first step in the above would be different.
|
||||
*
|
||||
* ------------
|
||||
* static struct attr_check *check;
|
||||
* static void setup_check(const char **argv)
|
||||
* {
|
||||
* check = attr_check_alloc();
|
||||
* while (*argv) {
|
||||
* struct git_attr *attr = git_attr(*argv);
|
||||
* attr_check_append(check, attr);
|
||||
* argv++;
|
||||
* }
|
||||
* }
|
||||
* ------------
|
||||
*
|
||||
*
|
||||
* Querying All Attributes
|
||||
* -----------------------
|
||||
*
|
||||
* To get the values of all attributes associated with a file:
|
||||
*
|
||||
* - Prepare an empty `attr_check` structure by calling `attr_check_alloc()`.
|
||||
*
|
||||
* - Call `git_all_attrs()`, which populates the `attr_check` with the
|
||||
* attributes attached to the path.
|
||||
*
|
||||
* - Iterate over the `attr_check.items[]` array to examine the attribute
|
||||
* names and values. The name of the attribute described by an
|
||||
* `attr_check.items[]` object can be retrieved via
|
||||
* `git_attr_name(check->items[i].attr)`. (Please note that no items will be
|
||||
* returned for unset attributes, so `ATTR_UNSET()` will return false for all
|
||||
* returned `attr_check.items[]` objects.)
|
||||
*
|
||||
* - Free the `attr_check` struct by calling `attr_check_free()`.
|
||||
*/
|
||||
|
||||
struct index_state;
|
||||
|
||||
/* An attribute is a pointer to this opaque structure */
|
||||
/**
|
||||
* An attribute is an opaque object that is identified by its name. Pass the
|
||||
* name to `git_attr()` function to obtain the object of this type.
|
||||
* The internal representation of this structure is of no interest to the
|
||||
* calling programs. The name of the attribute can be retrieved by calling
|
||||
* `git_attr_name()`.
|
||||
*/
|
||||
struct git_attr;
|
||||
|
||||
/* opaque structures used internally for attribute collection */
|
||||
@ -21,21 +133,36 @@ const struct git_attr *git_attr(const char *);
|
||||
extern const char git_attr__true[];
|
||||
extern const char git_attr__false[];
|
||||
|
||||
/* For public to check git_attr_check results */
|
||||
/**
|
||||
* Attribute Values
|
||||
* ----------------
|
||||
*
|
||||
* An attribute for a path can be in one of four states: Set, Unset, Unspecified
|
||||
* or set to a string, and `.value` member of `struct attr_check_item` records
|
||||
* it. The three macros check these, if none of them returns true, `.value`
|
||||
* member points at a string value of the attribute for the path.
|
||||
*/
|
||||
|
||||
/* Returns true if the attribute is Set for the path. */
|
||||
#define ATTR_TRUE(v) ((v) == git_attr__true)
|
||||
|
||||
/* Returns true if the attribute is Unset for the path. */
|
||||
#define ATTR_FALSE(v) ((v) == git_attr__false)
|
||||
|
||||
/* Returns true if the attribute is Unspecified for the path. */
|
||||
#define ATTR_UNSET(v) ((v) == NULL)
|
||||
|
||||
/*
|
||||
* Send one or more git_attr_check to git_check_attrs(), and
|
||||
* each 'value' member tells what its value is.
|
||||
* Unset one is returned as NULL.
|
||||
*/
|
||||
/* This structure represents one attribute and its value. */
|
||||
struct attr_check_item {
|
||||
const struct git_attr *attr;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents a collection of `attr_check_item`. It is passed to
|
||||
* `git_check_attr()` function, specifying the attributes to check, and
|
||||
* receives their values.
|
||||
*/
|
||||
struct attr_check {
|
||||
int nr;
|
||||
int alloc;
|
||||
|
41
cache.h
41
cache.h
@ -632,10 +632,43 @@ int daemonize(void);
|
||||
|
||||
#define alloc_nr(x) (((x)+16)*3/2)
|
||||
|
||||
/*
|
||||
* Realloc the buffer pointed at by variable 'x' so that it can hold
|
||||
* at least 'nr' entries; the number of entries currently allocated
|
||||
* is 'alloc', using the standard growing factor alloc_nr() macro.
|
||||
/**
|
||||
* Dynamically growing an array using realloc() is error prone and boring.
|
||||
*
|
||||
* Define your array with:
|
||||
*
|
||||
* - a pointer (`item`) that points at the array, initialized to `NULL`
|
||||
* (although please name the variable based on its contents, not on its
|
||||
* type);
|
||||
*
|
||||
* - an integer variable (`alloc`) that keeps track of how big the current
|
||||
* allocation is, initialized to `0`;
|
||||
*
|
||||
* - another integer variable (`nr`) to keep track of how many elements the
|
||||
* array currently has, initialized to `0`.
|
||||
*
|
||||
* Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
|
||||
* alloc)`. This ensures that the array can hold at least `n` elements by
|
||||
* calling `realloc(3)` and adjusting `alloc` variable.
|
||||
*
|
||||
* ------------
|
||||
* sometype *item;
|
||||
* size_t nr;
|
||||
* size_t alloc
|
||||
*
|
||||
* for (i = 0; i < nr; i++)
|
||||
* if (we like item[i] already)
|
||||
* return;
|
||||
*
|
||||
* // we did not like any existing one, so add one
|
||||
* ALLOC_GROW(item, nr + 1, alloc);
|
||||
* item[nr++] = value you like;
|
||||
* ------------
|
||||
*
|
||||
* You are responsible for updating the `nr` variable.
|
||||
*
|
||||
* If you need to specify the number of elements to allocate explicitly
|
||||
* then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`.
|
||||
*
|
||||
* Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some
|
||||
* added niceties.
|
||||
|
236
credential.h
236
credential.h
@ -3,8 +3,208 @@
|
||||
|
||||
#include "string-list.h"
|
||||
|
||||
/**
|
||||
* The credentials API provides an abstracted way of gathering username and
|
||||
* password credentials from the user.
|
||||
*
|
||||
* Typical setup
|
||||
* -------------
|
||||
*
|
||||
* ------------
|
||||
* +-----------------------+
|
||||
* | Git code (C) |--- to server requiring --->
|
||||
* | | authentication
|
||||
* |.......................|
|
||||
* | C credential API |--- prompt ---> User
|
||||
* +-----------------------+
|
||||
* ^ |
|
||||
* | pipe |
|
||||
* | v
|
||||
* +-----------------------+
|
||||
* | Git credential helper |
|
||||
* +-----------------------+
|
||||
* ------------
|
||||
*
|
||||
* The Git code (typically a remote-helper) will call the C API to obtain
|
||||
* credential data like a login/password pair (credential_fill). The
|
||||
* API will itself call a remote helper (e.g. "git credential-cache" or
|
||||
* "git credential-store") that may retrieve credential data from a
|
||||
* store. If the credential helper cannot find the information, the C API
|
||||
* will prompt the user. Then, the caller of the API takes care of
|
||||
* contacting the server, and does the actual authentication.
|
||||
*
|
||||
* C API
|
||||
* -----
|
||||
*
|
||||
* The credential C API is meant to be called by Git code which needs to
|
||||
* acquire or store a credential. It is centered around an object
|
||||
* representing a single credential and provides three basic operations:
|
||||
* fill (acquire credentials by calling helpers and/or prompting the user),
|
||||
* approve (mark a credential as successfully used so that it can be stored
|
||||
* for later use), and reject (mark a credential as unsuccessful so that it
|
||||
* can be erased from any persistent storage).
|
||||
*
|
||||
* Example
|
||||
* ~~~~~~~
|
||||
*
|
||||
* The example below shows how the functions of the credential API could be
|
||||
* used to login to a fictitious "foo" service on a remote host:
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* int foo_login(struct foo_connection *f)
|
||||
* {
|
||||
* int status;
|
||||
* // Create a credential with some context; we don't yet know the
|
||||
* // username or password.
|
||||
*
|
||||
* struct credential c = CREDENTIAL_INIT;
|
||||
* c.protocol = xstrdup("foo");
|
||||
* c.host = xstrdup(f->hostname);
|
||||
*
|
||||
* // Fill in the username and password fields by contacting
|
||||
* // helpers and/or asking the user. The function will die if it
|
||||
* // fails.
|
||||
* credential_fill(&c);
|
||||
*
|
||||
* // Otherwise, we have a username and password. Try to use it.
|
||||
*
|
||||
* status = send_foo_login(f, c.username, c.password);
|
||||
* switch (status) {
|
||||
* case FOO_OK:
|
||||
* // It worked. Store the credential for later use.
|
||||
* credential_accept(&c);
|
||||
* break;
|
||||
* case FOO_BAD_LOGIN:
|
||||
* // Erase the credential from storage so we don't try it again.
|
||||
* credential_reject(&c);
|
||||
* break;
|
||||
* default:
|
||||
* // Some other error occurred. We don't know if the
|
||||
* // credential is good or bad, so report nothing to the
|
||||
* // credential subsystem.
|
||||
* }
|
||||
*
|
||||
* // Free any associated resources.
|
||||
* credential_clear(&c);
|
||||
*
|
||||
* return status;
|
||||
* }
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* Credential Helpers
|
||||
* ------------------
|
||||
*
|
||||
* Credential helpers are programs executed by Git to fetch or save
|
||||
* credentials from and to long-term storage (where "long-term" is simply
|
||||
* longer than a single Git process; e.g., credentials may be stored
|
||||
* in-memory for a few minutes, or indefinitely on disk).
|
||||
*
|
||||
* Each helper is specified by a single string in the configuration
|
||||
* variable `credential.helper` (and others, see Documentation/git-config.txt).
|
||||
* The string is transformed by Git into a command to be executed using
|
||||
* these rules:
|
||||
*
|
||||
* 1. If the helper string begins with "!", it is considered a shell
|
||||
* snippet, and everything after the "!" becomes the command.
|
||||
*
|
||||
* 2. Otherwise, if the helper string begins with an absolute path, the
|
||||
* verbatim helper string becomes the command.
|
||||
*
|
||||
* 3. Otherwise, the string "git credential-" is prepended to the helper
|
||||
* string, and the result becomes the command.
|
||||
*
|
||||
* The resulting command then has an "operation" argument appended to it
|
||||
* (see below for details), and the result is executed by the shell.
|
||||
*
|
||||
* Here are some example specifications:
|
||||
*
|
||||
* ----------------------------------------------------
|
||||
* # run "git credential-foo"
|
||||
* foo
|
||||
*
|
||||
* # same as above, but pass an argument to the helper
|
||||
* foo --bar=baz
|
||||
*
|
||||
* # the arguments are parsed by the shell, so use shell
|
||||
* # quoting if necessary
|
||||
* foo --bar="whitespace arg"
|
||||
*
|
||||
* # you can also use an absolute path, which will not use the git wrapper
|
||||
* /path/to/my/helper --with-arguments
|
||||
*
|
||||
* # or you can specify your own shell snippet
|
||||
* !f() { echo "password=`cat $HOME/.secret`"; }; f
|
||||
* ----------------------------------------------------
|
||||
*
|
||||
* Generally speaking, rule (3) above is the simplest for users to specify.
|
||||
* Authors of credential helpers should make an effort to assist their
|
||||
* users by naming their program "git-credential-$NAME", and putting it in
|
||||
* the $PATH or $GIT_EXEC_PATH during installation, which will allow a user
|
||||
* to enable it with `git config credential.helper $NAME`.
|
||||
*
|
||||
* When a helper is executed, it will have one "operation" argument
|
||||
* appended to its command line, which is one of:
|
||||
*
|
||||
* `get`::
|
||||
*
|
||||
* Return a matching credential, if any exists.
|
||||
*
|
||||
* `store`::
|
||||
*
|
||||
* Store the credential, if applicable to the helper.
|
||||
*
|
||||
* `erase`::
|
||||
*
|
||||
* Remove a matching credential, if any, from the helper's storage.
|
||||
*
|
||||
* The details of the credential will be provided on the helper's stdin
|
||||
* stream. The exact format is the same as the input/output format of the
|
||||
* `git credential` plumbing command (see the section `INPUT/OUTPUT
|
||||
* FORMAT` in Documentation/git-credential.txt for a detailed specification).
|
||||
*
|
||||
* For a `get` operation, the helper should produce a list of attributes
|
||||
* on stdout in the same format. A helper is free to produce a subset, or
|
||||
* even no values at all if it has nothing useful to provide. Any provided
|
||||
* attributes will overwrite those already known about by Git. If a helper
|
||||
* outputs a `quit` attribute with a value of `true` or `1`, no further
|
||||
* helpers will be consulted, nor will the user be prompted (if no
|
||||
* credential has been provided, the operation will then fail).
|
||||
*
|
||||
* For a `store` or `erase` operation, the helper's output is ignored.
|
||||
* If it fails to perform the requested operation, it may complain to
|
||||
* stderr to inform the user. If it does not support the requested
|
||||
* operation (e.g., a read-only store), it should silently ignore the
|
||||
* request.
|
||||
*
|
||||
* If a helper receives any other operation, it should silently ignore the
|
||||
* request. This leaves room for future operations to be added (older
|
||||
* helpers will just ignore the new requests).
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This struct represents a single username/password combination
|
||||
* along with any associated context. All string fields should be
|
||||
* heap-allocated (or NULL if they are not known or not applicable).
|
||||
* The meaning of the individual context fields is the same as
|
||||
* their counterparts in the helper protocol.
|
||||
*
|
||||
* This struct should always be initialized with `CREDENTIAL_INIT` or
|
||||
* `credential_init`.
|
||||
*/
|
||||
struct credential {
|
||||
|
||||
/**
|
||||
* A `string_list` of helpers. Each string specifies an external
|
||||
* helper which will be run, in order, to either acquire or store
|
||||
* credentials. This list is filled-in by the API functions
|
||||
* according to the corresponding configuration variables before
|
||||
* consulting helpers, so there usually is no need for a caller to
|
||||
* modify the helpers field at all.
|
||||
*/
|
||||
struct string_list helpers;
|
||||
|
||||
unsigned approved:1,
|
||||
configured:1,
|
||||
quit:1,
|
||||
@ -19,16 +219,52 @@ struct credential {
|
||||
|
||||
#define CREDENTIAL_INIT { STRING_LIST_INIT_DUP }
|
||||
|
||||
/* Initialize a credential structure, setting all fields to empty. */
|
||||
void credential_init(struct credential *);
|
||||
|
||||
/**
|
||||
* Free any resources associated with the credential structure, returning
|
||||
* it to a pristine initialized state.
|
||||
*/
|
||||
void credential_clear(struct credential *);
|
||||
|
||||
/**
|
||||
* Instruct the credential subsystem to fill the username and
|
||||
* password fields of the passed credential struct by first
|
||||
* consulting helpers, then asking the user. After this function
|
||||
* returns, the username and password fields of the credential are
|
||||
* guaranteed to be non-NULL. If an error occurs, the function will
|
||||
* die().
|
||||
*/
|
||||
void credential_fill(struct credential *);
|
||||
|
||||
/**
|
||||
* Inform the credential subsystem that the provided credentials
|
||||
* were successfully used for authentication. This will cause the
|
||||
* credential subsystem to notify any helpers of the approval, so
|
||||
* that they may store the result to be used again. Any errors
|
||||
* from helpers are ignored.
|
||||
*/
|
||||
void credential_approve(struct credential *);
|
||||
|
||||
/**
|
||||
* Inform the credential subsystem that the provided credentials
|
||||
* have been rejected. This will cause the credential subsystem to
|
||||
* notify any helpers of the rejection (which allows them, for
|
||||
* example, to purge the invalid credentials from storage). It
|
||||
* will also free() the username and password fields of the
|
||||
* credential and set them to NULL (readying the credential for
|
||||
* another call to `credential_fill`). Any errors from helpers are
|
||||
* ignored.
|
||||
*/
|
||||
void credential_reject(struct credential *);
|
||||
|
||||
int credential_read(struct credential *, FILE *);
|
||||
void credential_write(const struct credential *, FILE *);
|
||||
|
||||
/* Parse a URL into broken-down credential fields. */
|
||||
void credential_from_url(struct credential *, const char *url);
|
||||
|
||||
int credential_match(const struct credential *have,
|
||||
const struct credential *want);
|
||||
|
||||
|
126
diff.h
126
diff.h
@ -9,6 +9,49 @@
|
||||
#include "object.h"
|
||||
#include "oidset.h"
|
||||
|
||||
/**
|
||||
* The diff API is for programs that compare two sets of files (e.g. two trees,
|
||||
* one tree and the index) and present the found difference in various ways.
|
||||
* The calling program is responsible for feeding the API pairs of files, one
|
||||
* from the "old" set and the corresponding one from "new" set, that are
|
||||
* different.
|
||||
* The library called through this API is called diffcore, and is responsible
|
||||
* for two things.
|
||||
*
|
||||
* - finding total rewrites (`-B`), renames (`-M`) and copies (`-C`), and
|
||||
* changes that touch a string (`-S`), as specified by the caller.
|
||||
*
|
||||
* - outputting the differences in various formats, as specified by the caller.
|
||||
*
|
||||
* Calling sequence
|
||||
* ----------------
|
||||
*
|
||||
* - Prepare `struct diff_options` to record the set of diff options, and then
|
||||
* call `repo_diff_setup()` to initialize this structure. This sets up the
|
||||
* vanilla default.
|
||||
*
|
||||
* - Fill in the options structure to specify desired output format, rename
|
||||
* detection, etc. `diff_opt_parse()` can be used to parse options given
|
||||
* from the command line in a way consistent with existing git-diff family
|
||||
* of programs.
|
||||
*
|
||||
* - Call `diff_setup_done()`; this inspects the options set up so far for
|
||||
* internal consistency and make necessary tweaking to it (e.g. if textual
|
||||
* patch output was asked, recursive behaviour is turned on); the callback
|
||||
* set_default in diff_options can be used to tweak this more.
|
||||
*
|
||||
* - As you find different pairs of files, call `diff_change()` to feed
|
||||
* modified files, `diff_addremove()` to feed created or deleted files, or
|
||||
* `diff_unmerge()` to feed a file whose state is 'unmerged' to the API.
|
||||
* These are thin wrappers to a lower-level `diff_queue()` function that is
|
||||
* flexible enough to record any of these kinds of changes.
|
||||
*
|
||||
* - Once you finish feeding the pairs of files, call `diffcore_std()`.
|
||||
* This will tell the diffcore library to go ahead and do its work.
|
||||
*
|
||||
* - Calling `diff_flush()` will produce the output.
|
||||
*/
|
||||
|
||||
struct combine_diff_path;
|
||||
struct commit;
|
||||
struct diff_filespec;
|
||||
@ -65,21 +108,66 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
|
||||
|
||||
#define DIFF_FLAGS_INIT { 0 }
|
||||
struct diff_flags {
|
||||
|
||||
/**
|
||||
* Tells if tree traversal done by tree-diff should recursively descend
|
||||
* into a tree object pair that are different in preimage and postimage set.
|
||||
*/
|
||||
unsigned recursive;
|
||||
unsigned tree_in_recursive;
|
||||
|
||||
/* Affects the way how a file that is seemingly binary is treated. */
|
||||
unsigned binary;
|
||||
unsigned text;
|
||||
|
||||
/**
|
||||
* Tells the patch output format not to use abbreviated object names on the
|
||||
* "index" lines.
|
||||
*/
|
||||
unsigned full_index;
|
||||
|
||||
/* Affects if diff-files shows removed files. */
|
||||
unsigned silent_on_remove;
|
||||
|
||||
/**
|
||||
* Tells the diffcore library that the caller is feeding unchanged
|
||||
* filepairs to allow copies from unmodified files be detected.
|
||||
*/
|
||||
unsigned find_copies_harder;
|
||||
|
||||
unsigned follow_renames;
|
||||
unsigned rename_empty;
|
||||
|
||||
/* Internal; used for optimization to see if there is any change. */
|
||||
unsigned has_changes;
|
||||
|
||||
unsigned quick;
|
||||
|
||||
/**
|
||||
* Tells diff-files that the input is not tracked files but files in random
|
||||
* locations on the filesystem.
|
||||
*/
|
||||
unsigned no_index;
|
||||
|
||||
/**
|
||||
* Tells output routine that it is Ok to call user specified patch output
|
||||
* routine. Plumbing disables this to ensure stable output.
|
||||
*/
|
||||
unsigned allow_external;
|
||||
|
||||
/**
|
||||
* For communication between the calling program and the options parser;
|
||||
* tell the calling program to signal the presence of difference using
|
||||
* program exit code.
|
||||
*/
|
||||
unsigned exit_with_status;
|
||||
|
||||
/**
|
||||
* Tells the library that the calling program is feeding the filepairs
|
||||
* reversed; `one` is two, and `two` is one.
|
||||
*/
|
||||
unsigned reverse_diff;
|
||||
|
||||
unsigned check_failed;
|
||||
unsigned relative_name;
|
||||
unsigned ignore_submodules;
|
||||
@ -131,36 +219,72 @@ enum diff_submodule_format {
|
||||
DIFF_SUBMODULE_INLINE_DIFF
|
||||
};
|
||||
|
||||
/**
|
||||
* the set of options the calling program wants to affect the operation of
|
||||
* diffcore library with.
|
||||
*/
|
||||
struct diff_options {
|
||||
const char *orderfile;
|
||||
|
||||
/**
|
||||
* A constant string (can and typically does contain newlines to look for
|
||||
* a block of text, not just a single line) to filter out the filepairs
|
||||
* that do not change the number of strings contained in its preimage and
|
||||
* postimage of the diff_queue.
|
||||
*/
|
||||
const char *pickaxe;
|
||||
|
||||
const char *single_follow;
|
||||
const char *a_prefix, *b_prefix;
|
||||
const char *line_prefix;
|
||||
size_t line_prefix_length;
|
||||
|
||||
/**
|
||||
* collection of boolean options that affects the operation, but some do
|
||||
* not have anything to do with the diffcore library.
|
||||
*/
|
||||
struct diff_flags flags;
|
||||
|
||||
/* diff-filter bits */
|
||||
unsigned int filter;
|
||||
|
||||
int use_color;
|
||||
|
||||
/* Number of context lines to generate in patch output. */
|
||||
int context;
|
||||
|
||||
int interhunkcontext;
|
||||
|
||||
/* Affects the way detection logic for complete rewrites, renames and
|
||||
* copies.
|
||||
*/
|
||||
int break_opt;
|
||||
int detect_rename;
|
||||
|
||||
int irreversible_delete;
|
||||
int skip_stat_unmatch;
|
||||
int line_termination;
|
||||
|
||||
/* The output format used when `diff_flush()` is run. */
|
||||
int output_format;
|
||||
|
||||
unsigned pickaxe_opts;
|
||||
|
||||
/* Affects the way detection logic for complete rewrites, renames and
|
||||
* copies.
|
||||
*/
|
||||
int rename_score;
|
||||
int rename_limit;
|
||||
|
||||
int needed_rename_limit;
|
||||
int degraded_cc_to_c;
|
||||
int show_rename_progress;
|
||||
int dirstat_permille;
|
||||
int setup;
|
||||
|
||||
/* Number of hexdigits to abbreviate raw format output to. */
|
||||
int abbrev;
|
||||
|
||||
int ita_invisible_in_index;
|
||||
/* white-space error highlighting */
|
||||
#define WSEH_NEW (1<<12)
|
||||
@ -192,6 +316,7 @@ struct diff_options {
|
||||
/* to support internal diff recursion by --follow hack*/
|
||||
int found_follow;
|
||||
|
||||
/* Callback which allows tweaking the options in diff_setup_done(). */
|
||||
void (*set_default)(struct diff_options *);
|
||||
|
||||
FILE *file;
|
||||
@ -286,6 +411,7 @@ enum color_diff {
|
||||
DIFF_FILE_OLD_BOLD = 21,
|
||||
DIFF_FILE_NEW_BOLD = 22,
|
||||
};
|
||||
|
||||
const char *diff_get_color(int diff_use_color, enum color_diff ix);
|
||||
#define diff_get_color_opt(o, ix) \
|
||||
diff_get_color((o)->use_color, ix)
|
||||
|
32
diffcore.h
32
diffcore.h
@ -28,6 +28,12 @@ struct userdiff_driver;
|
||||
|
||||
#define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */
|
||||
|
||||
/**
|
||||
* the internal representation for a single file (blob). It records the blob
|
||||
* object name (if known -- for a work tree file it typically is a NUL SHA-1),
|
||||
* filemode and pathname. This is what the `diff_addremove()`, `diff_change()`
|
||||
* and `diff_unmerge()` synthesize and feed `diff_queue()` function with.
|
||||
*/
|
||||
struct diff_filespec {
|
||||
struct object_id oid;
|
||||
char *path;
|
||||
@ -66,6 +72,17 @@ void diff_free_filespec_data(struct diff_filespec *);
|
||||
void diff_free_filespec_blob(struct diff_filespec *);
|
||||
int diff_filespec_is_binary(struct repository *, struct diff_filespec *);
|
||||
|
||||
/**
|
||||
* This records a pair of `struct diff_filespec`; the filespec for a file in
|
||||
* the "old" set (i.e. preimage) is called `one`, and the filespec for a file
|
||||
* in the "new" set (i.e. postimage) is called `two`. A change that represents
|
||||
* file creation has NULL in `one`, and file deletion has NULL in `two`.
|
||||
*
|
||||
* A `filepair` starts pointing at `one` and `two` that are from the same
|
||||
* filename, but `diffcore_std()` can break pairs and match component filespecs
|
||||
* with other filespecs from a different filepair to form new filepair. This is
|
||||
* called 'rename detection'.
|
||||
*/
|
||||
struct diff_filepair {
|
||||
struct diff_filespec *one;
|
||||
struct diff_filespec *two;
|
||||
@ -77,6 +94,7 @@ struct diff_filepair {
|
||||
unsigned done_skip_stat_unmatch : 1;
|
||||
unsigned skip_stat_unmatch_result : 1;
|
||||
};
|
||||
|
||||
#define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged)
|
||||
|
||||
#define DIFF_PAIR_RENAME(p) ((p)->renamed_pair)
|
||||
@ -94,11 +112,25 @@ void diff_free_filepair(struct diff_filepair *);
|
||||
|
||||
int diff_unmodified_pair(struct diff_filepair *);
|
||||
|
||||
/**
|
||||
* This is a collection of filepairs. Notable members are:
|
||||
*
|
||||
* - `queue`:
|
||||
* An array of pointers to `struct diff_filepair`. This dynamically grows as
|
||||
* you add filepairs;
|
||||
*
|
||||
* - `alloc`:
|
||||
* The allocated size of the `queue` array;
|
||||
*
|
||||
* - `nr`:
|
||||
* The number of elements in the `queue` array.
|
||||
*/
|
||||
struct diff_queue_struct {
|
||||
struct diff_filepair **queue;
|
||||
int alloc;
|
||||
int nr;
|
||||
};
|
||||
|
||||
#define DIFF_QUEUE_CLEAR(q) \
|
||||
do { \
|
||||
(q)->queue = NULL; \
|
||||
|
2
dir.c
2
dir.c
@ -2,8 +2,6 @@
|
||||
* This handles recursive filename detection with exclude
|
||||
* files, index knowledge etc..
|
||||
*
|
||||
* See Documentation/technical/api-directory-listing.txt
|
||||
*
|
||||
* Copyright (C) Linus Torvalds, 2005-2006
|
||||
* Junio Hamano, 2005-2006
|
||||
*/
|
||||
|
119
dir.h
119
dir.h
@ -1,11 +1,44 @@
|
||||
#ifndef DIR_H
|
||||
#define DIR_H
|
||||
|
||||
/* See Documentation/technical/api-directory-listing.txt */
|
||||
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/**
|
||||
* The directory listing API is used to enumerate paths in the work tree,
|
||||
* optionally taking `.git/info/exclude` and `.gitignore` files per directory
|
||||
* into account.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calling sequence
|
||||
* ----------------
|
||||
*
|
||||
* Note: The index may be checked for .gitignore files that are
|
||||
* CE_SKIP_WORKTREE marked. If you want to exclude files, make sure you have
|
||||
* loaded the index first.
|
||||
*
|
||||
* - Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
|
||||
* sizeof(dir))`.
|
||||
*
|
||||
* - To add single exclude pattern, call `add_pattern_list()` and then
|
||||
* `add_pattern()`.
|
||||
*
|
||||
* - To add patterns from a file (e.g. `.git/info/exclude`), call
|
||||
* `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. A
|
||||
* short-hand function `setup_standard_excludes()` can be used to set
|
||||
* up the standard set of exclude settings.
|
||||
*
|
||||
* - Set options described in the Data Structure section above.
|
||||
*
|
||||
* - Call `read_directory()`.
|
||||
*
|
||||
* - Use `dir.entries[]`.
|
||||
*
|
||||
* - Call `clear_directory()` when none of the contained elements are no longer in use.
|
||||
*
|
||||
*/
|
||||
|
||||
struct dir_entry {
|
||||
unsigned int len;
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
@ -144,25 +177,101 @@ struct untracked_cache {
|
||||
unsigned int use_fsmonitor : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* structure is used to pass directory traversal options to the library and to
|
||||
* record the paths discovered. A single `struct dir_struct` is used regardless
|
||||
* of whether or not the traversal recursively descends into subdirectories.
|
||||
*/
|
||||
struct dir_struct {
|
||||
int nr, alloc;
|
||||
int ignored_nr, ignored_alloc;
|
||||
|
||||
/* The number of members in `entries[]` array. */
|
||||
int nr;
|
||||
|
||||
/* Internal use; keeps track of allocation of `entries[]` array.*/
|
||||
int alloc;
|
||||
|
||||
/* The number of members in `ignored[]` array. */
|
||||
int ignored_nr;
|
||||
|
||||
int ignored_alloc;
|
||||
|
||||
/* bit-field of options */
|
||||
enum {
|
||||
|
||||
/**
|
||||
* Return just ignored files in `entries[]`, not untracked files.
|
||||
* This flag is mutually exclusive with `DIR_SHOW_IGNORED_TOO`.
|
||||
*/
|
||||
DIR_SHOW_IGNORED = 1<<0,
|
||||
|
||||
/* Include a directory that is not tracked. */
|
||||
DIR_SHOW_OTHER_DIRECTORIES = 1<<1,
|
||||
|
||||
/* Do not include a directory that is not tracked and is empty. */
|
||||
DIR_HIDE_EMPTY_DIRECTORIES = 1<<2,
|
||||
|
||||
/**
|
||||
* If set, recurse into a directory that looks like a Git directory.
|
||||
* Otherwise it is shown as a directory.
|
||||
*/
|
||||
DIR_NO_GITLINKS = 1<<3,
|
||||
|
||||
/**
|
||||
* Special mode for git-add. Return ignored files in `ignored[]` and
|
||||
* untracked files in `entries[]`. Only returns ignored files that match
|
||||
* pathspec exactly (no wildcards). Does not recurse into ignored
|
||||
* directories.
|
||||
*/
|
||||
DIR_COLLECT_IGNORED = 1<<4,
|
||||
|
||||
/**
|
||||
* Similar to `DIR_SHOW_IGNORED`, but return ignored files in
|
||||
* `ignored[]` in addition to untracked files in `entries[]`.
|
||||
* This flag is mutually exclusive with `DIR_SHOW_IGNORED`.
|
||||
*/
|
||||
DIR_SHOW_IGNORED_TOO = 1<<5,
|
||||
|
||||
DIR_COLLECT_KILLED_ONLY = 1<<6,
|
||||
|
||||
/**
|
||||
* Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is
|
||||
* set, the untracked contents of untracked directories are also
|
||||
* returned in `entries[]`.
|
||||
*/
|
||||
DIR_KEEP_UNTRACKED_CONTENTS = 1<<7,
|
||||
|
||||
/**
|
||||
* Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is
|
||||
* set, returns ignored files and directories that match an exclude
|
||||
* pattern. If a directory matches an exclude pattern, then the
|
||||
* directory is returned and the contained paths are not. A directory
|
||||
* that does not match an exclude pattern will not be returned even if
|
||||
* all of its contents are ignored. In this case, the contents are
|
||||
* returned as individual entries.
|
||||
*
|
||||
* If this is set, files and directories that explicitly match an ignore
|
||||
* pattern are reported. Implicitly ignored directories (directories that
|
||||
* do not match an ignore pattern, but whose contents are all ignored)
|
||||
* are not reported, instead all of the contents are reported.
|
||||
*/
|
||||
DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8,
|
||||
|
||||
DIR_SKIP_NESTED_GIT = 1<<9
|
||||
} flags;
|
||||
|
||||
/* An array of `struct dir_entry`, each element of which describes a path. */
|
||||
struct dir_entry **entries;
|
||||
|
||||
/**
|
||||
* used for ignored paths with the `DIR_SHOW_IGNORED_TOO` and
|
||||
* `DIR_COLLECT_IGNORED` flags.
|
||||
*/
|
||||
struct dir_entry **ignored;
|
||||
|
||||
/* Exclude info */
|
||||
/**
|
||||
* The name of the file to be read in each directory for excluded files
|
||||
* (typically `.gitignore`).
|
||||
*/
|
||||
const char *exclude_per_dir;
|
||||
|
||||
/*
|
||||
|
1
graph.c
1
graph.c
@ -34,6 +34,7 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb);
|
||||
* handle directly. It is assumed that this is the same file handle as the
|
||||
* file specified by the graph diff options. This is necessary so that
|
||||
* graph_show_strbuf can be called even with a NULL graph.
|
||||
* If a NULL graph is supplied, the strbuf is printed as-is.
|
||||
*/
|
||||
static void graph_show_strbuf(struct git_graph *graph,
|
||||
FILE *file,
|
||||
|
121
graph.h
121
graph.h
@ -2,6 +2,103 @@
|
||||
#define GRAPH_H
|
||||
#include "diff.h"
|
||||
|
||||
/**
|
||||
* The graph API is used to draw a text-based representation of the commit
|
||||
* history. The API generates the graph in a line-by-line fashion.
|
||||
*
|
||||
* Calling sequence
|
||||
* ----------------
|
||||
*
|
||||
* - Create a `struct git_graph` by calling `graph_init()`. When using the
|
||||
* revision walking API, this is done automatically by `setup_revisions()` if
|
||||
* the '--graph' option is supplied.
|
||||
*
|
||||
* - Use the revision walking API to walk through a group of contiguous commits.
|
||||
* The `get_revision()` function automatically calls `graph_update()` each time
|
||||
* it is invoked.
|
||||
*
|
||||
* - For each commit, call `graph_next_line()` repeatedly, until
|
||||
* `graph_is_commit_finished()` returns non-zero. Each call to
|
||||
* `graph_next_line()` will output a single line of the graph. The resulting
|
||||
* lines will not contain any newlines. `graph_next_line()` returns 1 if the
|
||||
* resulting line contains the current commit, or 0 if this is merely a line
|
||||
* needed to adjust the graph before or after the current commit. This return
|
||||
* value can be used to determine where to print the commit summary information
|
||||
* alongside the graph output.
|
||||
*
|
||||
* Limitations
|
||||
* -----------
|
||||
* - Check the graph_update() function for its limitations.
|
||||
*
|
||||
* - The graph API does not currently support reverse commit ordering. In
|
||||
* order to implement reverse ordering, the graphing API needs an
|
||||
* (efficient) mechanism to find the children of a commit.
|
||||
*
|
||||
* Sample usage
|
||||
* ------------
|
||||
*
|
||||
* ------------
|
||||
* struct commit *commit;
|
||||
* struct git_graph *graph = graph_init(opts);
|
||||
*
|
||||
* while ((commit = get_revision(opts)) != NULL) {
|
||||
* while (!graph_is_commit_finished(graph))
|
||||
* {
|
||||
* struct strbuf sb;
|
||||
* int is_commit_line;
|
||||
*
|
||||
* strbuf_init(&sb, 0);
|
||||
* is_commit_line = graph_next_line(graph, &sb);
|
||||
* fputs(sb.buf, stdout);
|
||||
*
|
||||
* if (is_commit_line)
|
||||
* log_tree_commit(opts, commit);
|
||||
* else
|
||||
* putchar(opts->diffopt.line_termination);
|
||||
* }
|
||||
* }
|
||||
* ------------
|
||||
* Sample output
|
||||
* -------------
|
||||
*
|
||||
* The following is an example of the output from the graph API. This output does
|
||||
* not include any commit summary information--callers are responsible for
|
||||
* outputting that information, if desired.
|
||||
* ------------
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* |\
|
||||
* * |
|
||||
* | | *
|
||||
* | \ \
|
||||
* | \ \
|
||||
* *-. \ \
|
||||
* |\ \ \ \
|
||||
* | | * | |
|
||||
* | | | | | *
|
||||
* | | | | | *
|
||||
* | | | | | *
|
||||
* | | | | | |\
|
||||
* | | | | | | *
|
||||
* | * | | | | |
|
||||
* | | | | | * \
|
||||
* | | | | | |\ |
|
||||
* | | | | * | | |
|
||||
* | | | | * | | |
|
||||
* * | | | | | | |
|
||||
* | |/ / / / / /
|
||||
* |/| / / / / /
|
||||
* * | | | | | |
|
||||
* |/ / / / / /
|
||||
* * | | | | |
|
||||
* | | | | | *
|
||||
* | | | | |/
|
||||
* | | | | *
|
||||
* ------------
|
||||
*
|
||||
*/
|
||||
|
||||
/* A graph is a pointer to this opaque structure */
|
||||
struct git_graph;
|
||||
|
||||
@ -50,6 +147,21 @@ struct git_graph *graph_init(struct rev_info *opt);
|
||||
* If graph_update() is called before graph_is_commit_finished() returns 1,
|
||||
* the next call to graph_next_line() will output an ellipsis ("...")
|
||||
* to indicate that a portion of the graph is missing.
|
||||
*
|
||||
* Limitations:
|
||||
* -----------
|
||||
*
|
||||
* - `graph_update()` must be called with commits in topological order. It should
|
||||
* not be called on a commit if it has already been invoked with an ancestor of
|
||||
* that commit, or the graph output will be incorrect.
|
||||
*
|
||||
* - `graph_update()` must be called on a contiguous group of commits. If
|
||||
* `graph_update()` is called on a particular commit, it should later be called
|
||||
* on all parents of that commit. Parents must not be skipped, or the graph
|
||||
* output will appear incorrect.
|
||||
*
|
||||
* - `graph_update()` may be used on a pruned set of commits only if the parent list
|
||||
* has been rewritten so as to include only ancestors from the pruned set.
|
||||
*/
|
||||
void graph_update(struct git_graph *graph, struct commit *commit);
|
||||
|
||||
@ -62,6 +174,10 @@ void graph_update(struct git_graph *graph, struct commit *commit);
|
||||
* for this commit. If 0 is returned, graph_next_line() may still be
|
||||
* called without calling graph_update(), and it will merely output
|
||||
* appropriate "vertical padding" in the graph.
|
||||
*
|
||||
* If `graph_update()` is called before all lines for the current commit have
|
||||
* been printed, the next call to `graph_next_line()` will output an ellipsis,
|
||||
* to indicate that a portion of the graph was omitted.
|
||||
*/
|
||||
int graph_is_commit_finished(struct git_graph const *graph);
|
||||
|
||||
@ -112,6 +228,7 @@ void graph_show_padding(struct git_graph *graph);
|
||||
/*
|
||||
* If the graph is non-NULL, print the rest of the history graph for this
|
||||
* commit to stdout. Does not print a terminating newline on the last line.
|
||||
* Returns 1 if output was printed, and 0 if no output was necessary.
|
||||
*/
|
||||
int graph_show_remainder(struct git_graph *graph);
|
||||
|
||||
@ -121,6 +238,10 @@ int graph_show_remainder(struct git_graph *graph);
|
||||
* This is similar to graph_show_strbuf(), but it always prints the
|
||||
* remainder of the graph.
|
||||
*
|
||||
* It is better than directly calling `graph_show_strbuf()` followed by
|
||||
* `graph_show_remainder()` since it properly handles buffers that do not end in
|
||||
* a terminating newline.
|
||||
*
|
||||
* If the strbuf ends with a newline, the output printed by
|
||||
* graph_show_commit_msg() will end with a newline. If the strbuf is
|
||||
* missing a terminating newline (including if it is empty), the output
|
||||
|
73
ll-merge.h
73
ll-merge.h
@ -7,16 +7,87 @@
|
||||
|
||||
#include "xdiff/xdiff.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* Calling sequence:
|
||||
* ----------------
|
||||
*
|
||||
* - Prepare a `struct ll_merge_options` to record options.
|
||||
* If you have no special requests, skip this and pass `NULL`
|
||||
* as the `opts` parameter to use the default options.
|
||||
*
|
||||
* - Allocate an mmbuffer_t variable for the result.
|
||||
*
|
||||
* - Allocate and fill variables with the file's original content
|
||||
* and two modified versions (using `read_mmfile`, for example).
|
||||
*
|
||||
* - Call `ll_merge()`.
|
||||
*
|
||||
* - Read the merged content from `result_buf.ptr` and `result_buf.size`.
|
||||
*
|
||||
* - Release buffers when finished. A simple
|
||||
* `free(ancestor.ptr); free(ours.ptr); free(theirs.ptr);
|
||||
* free(result_buf.ptr);` will do.
|
||||
*
|
||||
* If the modifications do not merge cleanly, `ll_merge` will return a
|
||||
* nonzero value and `result_buf` will generally include a description of
|
||||
* the conflict bracketed by markers such as the traditional `<<<<<<<`
|
||||
* and `>>>>>>>`.
|
||||
*
|
||||
* The `ancestor_label`, `our_label`, and `their_label` parameters are
|
||||
* used to label the different sides of a conflict if the merge driver
|
||||
* supports this.
|
||||
*/
|
||||
|
||||
|
||||
struct index_state;
|
||||
|
||||
/**
|
||||
* This describes the set of options the calling program wants to affect
|
||||
* the operation of a low-level (single file) merge.
|
||||
*/
|
||||
struct ll_merge_options {
|
||||
|
||||
/**
|
||||
* Behave as though this were part of a merge between common ancestors in
|
||||
* a recursive merge (merges of binary files may need to be handled
|
||||
* differently in such cases, for example). If a helper program is
|
||||
* specified by the `[merge "<driver>"] recursive` configuration, it will
|
||||
* be used.
|
||||
*/
|
||||
unsigned virtual_ancestor : 1;
|
||||
unsigned variant : 2; /* favor ours, favor theirs, or union merge */
|
||||
|
||||
/**
|
||||
* Resolve local conflicts automatically in favor of one side or the other
|
||||
* (as in 'git merge-file' `--ours`/`--theirs`/`--union`). Can be `0`,
|
||||
* `XDL_MERGE_FAVOR_OURS`, `XDL_MERGE_FAVOR_THEIRS`,
|
||||
* or `XDL_MERGE_FAVOR_UNION`.
|
||||
*/
|
||||
unsigned variant : 2;
|
||||
|
||||
/**
|
||||
* Resmudge and clean the "base", "theirs" and "ours" files before merging.
|
||||
* Use this when the merge is likely to have overlapped with a change in
|
||||
* smudge/clean or end-of-line normalization rules.
|
||||
*/
|
||||
unsigned renormalize : 1;
|
||||
|
||||
/**
|
||||
* Increase the length of conflict markers so that nested conflicts
|
||||
* can be differentiated.
|
||||
*/
|
||||
unsigned extra_marker_size;
|
||||
|
||||
/* Extra xpparam_t flags as defined in xdiff/xdiff.h. */
|
||||
long xdl_opts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform a three-way single-file merge in core. This is a thin wrapper
|
||||
* around `xdl_merge` that takes the path and any merge backend specified in
|
||||
* `.gitattributes` or `.git/info/attributes` into account.
|
||||
* Returns 0 for a clean merge.
|
||||
*/
|
||||
int ll_merge(mmbuffer_t *result_buf,
|
||||
const char *path,
|
||||
mmfile_t *ancestor, const char *ancestor_label,
|
||||
|
@ -1,6 +1,10 @@
|
||||
#ifndef PARSE_OPTIONS_H
|
||||
#define PARSE_OPTIONS_H
|
||||
|
||||
/**
|
||||
* Refer to Documentation/technical/api-parse-options.txt for the API doc.
|
||||
*/
|
||||
|
||||
enum parse_opt_type {
|
||||
/* special types */
|
||||
OPTION_END,
|
||||
|
35
pathspec.h
35
pathspec.h
@ -22,6 +22,11 @@ struct index_state;
|
||||
|
||||
#define PATHSPEC_ONESTAR 1 /* the pathspec pattern satisfies GFNM_ONESTAR */
|
||||
|
||||
/**
|
||||
* See glossary-context.txt for the syntax of pathspec.
|
||||
* In memory, a pathspec set is represented by "struct pathspec" and is
|
||||
* prepared by parse_pathspec().
|
||||
*/
|
||||
struct pathspec {
|
||||
int nr;
|
||||
unsigned int has_wildcard:1;
|
||||
@ -73,12 +78,39 @@ struct pathspec {
|
||||
*/
|
||||
#define PATHSPEC_LITERAL_PATH (1<<6)
|
||||
|
||||
/*
|
||||
/**
|
||||
* Given command line arguments and a prefix, convert the input to
|
||||
* pathspec. die() if any magic in magic_mask is used.
|
||||
*
|
||||
* Any arguments used are copied. It is safe for the caller to modify
|
||||
* or free 'prefix' and 'args' after calling this function.
|
||||
*
|
||||
* - magic_mask specifies what features that are NOT supported by the following
|
||||
* code. If a user attempts to use such a feature, parse_pathspec() can reject
|
||||
* it early.
|
||||
*
|
||||
* - flags specifies other things that the caller wants parse_pathspec to
|
||||
* perform.
|
||||
*
|
||||
* - prefix and args come from cmd_* functions
|
||||
*
|
||||
* parse_pathspec() helps catch unsupported features and reject them politely.
|
||||
* At a lower level, different pathspec-related functions may not support the
|
||||
* same set of features. Such pathspec-sensitive functions are guarded with
|
||||
* GUARD_PATHSPEC(), which will die in an unfriendly way when an unsupported
|
||||
* feature is requested.
|
||||
*
|
||||
* The command designers are supposed to make sure that GUARD_PATHSPEC() never
|
||||
* dies. They have to make sure all unsupported features are caught by
|
||||
* parse_pathspec(), not by GUARD_PATHSPEC. grepping GUARD_PATHSPEC() should
|
||||
* give the designers all pathspec-sensitive codepaths and what features they
|
||||
* support.
|
||||
*
|
||||
* A similar process is applied when a new pathspec magic is added. The designer
|
||||
* lifts the GUARD_PATHSPEC restriction in the functions that support the new
|
||||
* magic. At the same time (s)he has to make sure this new feature will be
|
||||
* caught at parse_pathspec() in commands that cannot handle the new magic in
|
||||
* some cases. grepping parse_pathspec() should help.
|
||||
*/
|
||||
void parse_pathspec(struct pathspec *pathspec,
|
||||
unsigned magic_mask,
|
||||
@ -95,6 +127,7 @@ void parse_pathspec_file(struct pathspec *pathspec,
|
||||
const char *prefix,
|
||||
const char *file,
|
||||
int nul_term_line);
|
||||
|
||||
void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
|
||||
void clear_pathspec(struct pathspec *);
|
||||
|
||||
|
51
refs.h
51
refs.h
@ -310,19 +310,35 @@ int refs_for_each_branch_ref(struct ref_store *refs,
|
||||
int refs_for_each_remote_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/* just iterates the head ref. */
|
||||
int head_ref(each_ref_fn fn, void *cb_data);
|
||||
|
||||
/* iterates all refs. */
|
||||
int for_each_ref(each_ref_fn fn, void *cb_data);
|
||||
|
||||
/**
|
||||
* iterates all refs which have a defined prefix and strips that prefix from
|
||||
* the passed variable refname.
|
||||
*/
|
||||
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
|
||||
|
||||
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data,
|
||||
unsigned int broken);
|
||||
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
|
||||
unsigned int broken);
|
||||
|
||||
/**
|
||||
* iterate refs from the respective area.
|
||||
*/
|
||||
int for_each_tag_ref(each_ref_fn fn, void *cb_data);
|
||||
int for_each_branch_ref(each_ref_fn fn, void *cb_data);
|
||||
int for_each_remote_ref(each_ref_fn fn, void *cb_data);
|
||||
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data);
|
||||
|
||||
/* iterates all refs that match the specified glob pattern. */
|
||||
int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
|
||||
|
||||
int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
|
||||
const char *prefix, void *cb_data);
|
||||
|
||||
@ -791,6 +807,41 @@ int reflog_expire(const char *refname, const struct object_id *oid,
|
||||
int ref_storage_backend_exists(const char *name);
|
||||
|
||||
struct ref_store *get_main_ref_store(struct repository *r);
|
||||
|
||||
/**
|
||||
* Submodules
|
||||
* ----------
|
||||
*
|
||||
* If you want to iterate the refs of a submodule you first need to add the
|
||||
* submodules object database. You can do this by a code-snippet like
|
||||
* this:
|
||||
*
|
||||
* const char *path = "path/to/submodule"
|
||||
* if (add_submodule_odb(path))
|
||||
* die("Error submodule '%s' not populated.", path);
|
||||
*
|
||||
* `add_submodule_odb()` will return zero on success. If you
|
||||
* do not do this you will get an error for each ref that it does not point
|
||||
* to a valid object.
|
||||
*
|
||||
* Note: As a side-effect of this you cannot safely assume that all
|
||||
* objects you lookup are available in superproject. All submodule objects
|
||||
* will be available the same way as the superprojects objects.
|
||||
*
|
||||
* Example:
|
||||
* --------
|
||||
*
|
||||
* ----
|
||||
* static int handle_remote_ref(const char *refname,
|
||||
* const unsigned char *sha1, int flags, void *cb_data)
|
||||
* {
|
||||
* struct strbuf *output = cb_data;
|
||||
* strbuf_addf(output, "%s\n", refname);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return the ref_store instance for the specified submodule. For the
|
||||
* main repository, use submodule==NULL; such a call cannot fail. For
|
||||
|
16
refspec.h
16
refspec.h
@ -20,6 +20,22 @@ struct refspec_item {
|
||||
#define REFSPEC_INIT_FETCH { .fetch = REFSPEC_FETCH }
|
||||
#define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH }
|
||||
|
||||
/**
|
||||
* A struct refspec holds the parsed interpretation of a refspec. If it will
|
||||
* force updates (starts with a '+'), force is true. If it is a pattern
|
||||
* (sides end with '*') pattern is true. src and dest are the two sides
|
||||
* (including '*' characters if present); if there is only one side, it is src,
|
||||
* and dst is NULL; if sides exist but are empty (i.e., the refspec either
|
||||
* starts or ends with ':'), the corresponding side is "".
|
||||
*
|
||||
* An array of strings can be parsed into an array of struct refspecs using
|
||||
* parse_fetch_refspec() or parse_push_refspec().
|
||||
*
|
||||
* remote_find_tracking(), given a remote and a struct refspec with either src
|
||||
* or dst filled out, will fill out the other such that the result is in the
|
||||
* "fetch" specification for the remote (note that this evaluates patterns and
|
||||
* returns a single result).
|
||||
*/
|
||||
struct refspec {
|
||||
struct refspec_item *items;
|
||||
int alloc;
|
||||
|
57
remote.h
57
remote.h
@ -6,6 +6,14 @@
|
||||
#include "hashmap.h"
|
||||
#include "refspec.h"
|
||||
|
||||
/**
|
||||
* The API gives access to the configuration related to remotes. It handles
|
||||
* all three configuration mechanisms historically and currently used by Git,
|
||||
* and presents the information in a uniform fashion. Note that the code also
|
||||
* handles plain URLs without any configuration, giving them just the default
|
||||
* information.
|
||||
*/
|
||||
|
||||
enum {
|
||||
REMOTE_UNCONFIGURED = 0,
|
||||
REMOTE_CONFIG,
|
||||
@ -16,16 +24,22 @@ enum {
|
||||
struct remote {
|
||||
struct hashmap_entry ent;
|
||||
|
||||
/* The user's nickname for the remote */
|
||||
const char *name;
|
||||
|
||||
int origin, configured_in_repo;
|
||||
|
||||
const char *foreign_vcs;
|
||||
|
||||
/* An array of all of the url_nr URLs configured for the remote */
|
||||
const char **url;
|
||||
|
||||
int url_nr;
|
||||
int url_alloc;
|
||||
|
||||
/* An array of all of the pushurl_nr push URLs configured for the remote */
|
||||
const char **pushurl;
|
||||
|
||||
int pushurl_nr;
|
||||
int pushurl_alloc;
|
||||
|
||||
@ -34,32 +48,47 @@ struct remote {
|
||||
struct refspec fetch;
|
||||
|
||||
/*
|
||||
* The setting for whether to fetch tags (as a separate rule from the
|
||||
* configured refspecs);
|
||||
* -1 to never fetch tags
|
||||
* 0 to auto-follow tags on heuristic (default)
|
||||
* 1 to always auto-follow tags
|
||||
* 2 to always fetch tags
|
||||
*/
|
||||
int fetch_tags;
|
||||
|
||||
int skip_default_update;
|
||||
int mirror;
|
||||
int prune;
|
||||
int prune_tags;
|
||||
|
||||
/**
|
||||
* The configured helper programs to run on the remote side, for
|
||||
* Git-native protocols.
|
||||
*/
|
||||
const char *receivepack;
|
||||
const char *uploadpack;
|
||||
|
||||
/*
|
||||
* for curl remotes only
|
||||
*/
|
||||
/* The proxy to use for curl (http, https, ftp, etc.) URLs. */
|
||||
char *http_proxy;
|
||||
|
||||
/* The method used for authenticating against `http_proxy`. */
|
||||
char *http_proxy_authmethod;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct remotes can be found by name with remote_get().
|
||||
* remote_get(NULL) will return the default remote, given the current branch
|
||||
* and configuration.
|
||||
*/
|
||||
struct remote *remote_get(const char *name);
|
||||
|
||||
struct remote *pushremote_get(const char *name);
|
||||
int remote_is_configured(struct remote *remote, int in_repo);
|
||||
|
||||
typedef int each_remote_fn(struct remote *remote, void *priv);
|
||||
|
||||
/* iterate through struct remotes */
|
||||
int for_each_remote(each_remote_fn fn, void *priv);
|
||||
|
||||
int remote_has_url(struct remote *remote, const char *url);
|
||||
@ -194,16 +223,36 @@ struct ref *get_remote_ref(const struct ref *remote_refs, const char *name);
|
||||
*/
|
||||
int remote_find_tracking(struct remote *remote, struct refspec_item *refspec);
|
||||
|
||||
/**
|
||||
* struct branch holds the configuration for a branch. It can be looked up with
|
||||
* branch_get(name) for "refs/heads/{name}", or with branch_get(NULL) for HEAD.
|
||||
*/
|
||||
struct branch {
|
||||
|
||||
/* The short name of the branch. */
|
||||
const char *name;
|
||||
|
||||
/* The full path for the branch ref. */
|
||||
const char *refname;
|
||||
|
||||
/* The name of the remote listed in the configuration. */
|
||||
const char *remote_name;
|
||||
|
||||
const char *pushremote_name;
|
||||
|
||||
/* An array of the "merge" lines in the configuration. */
|
||||
const char **merge_name;
|
||||
|
||||
/**
|
||||
* An array of the struct refspecs used for the merge lines. That is,
|
||||
* merge[i]->dst is a local tracking ref which should be merged into this
|
||||
* branch by default.
|
||||
*/
|
||||
struct refspec_item **merge;
|
||||
|
||||
/* The number of merge configurations */
|
||||
int merge_nr;
|
||||
|
||||
int merge_alloc;
|
||||
|
||||
const char *push_tracking_ref;
|
||||
@ -215,7 +264,9 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit);
|
||||
const char *remote_ref_for_branch(struct branch *branch, int for_push,
|
||||
int *explicit);
|
||||
|
||||
/* returns true if the given branch has merge configuration given. */
|
||||
int branch_has_merge_config(struct branch *branch);
|
||||
|
||||
int branch_merge_matches(struct branch *, int n, const char *);
|
||||
|
||||
/**
|
||||
|
59
revision.h
59
revision.h
@ -9,6 +9,19 @@
|
||||
#include "diff.h"
|
||||
#include "commit-slab-decl.h"
|
||||
|
||||
/**
|
||||
* The revision walking API offers functions to build a list of revisions
|
||||
* and then iterate over that list.
|
||||
*
|
||||
* Calling sequence
|
||||
* ----------------
|
||||
*
|
||||
* The walking API has a given calling sequence: first you need to initialize
|
||||
* a rev_info structure, then add revisions to control what kind of revision
|
||||
* list do you want to get, finally you can iterate over the revision list.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Remember to update object flag allocation in object.h */
|
||||
#define SEEN (1u<<0)
|
||||
#define UNINTERESTING (1u<<1)
|
||||
@ -306,11 +319,29 @@ struct setup_revision_opt {
|
||||
#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
|
||||
#define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize a rev_info structure with default values. The third parameter may
|
||||
* be NULL or can be prefix path, and then the `.prefix` variable will be set
|
||||
* to it. This is typically the first function you want to call when you want
|
||||
* to deal with a revision list. After calling this function, you are free to
|
||||
* customize options, like set `.ignore_merges` to 0 if you don't want to
|
||||
* ignore merges, and so on.
|
||||
*/
|
||||
void repo_init_revisions(struct repository *r,
|
||||
struct rev_info *revs,
|
||||
const char *prefix);
|
||||
|
||||
/**
|
||||
* Parse revision information, filling in the `rev_info` structure, and
|
||||
* removing the used arguments from the argument list. Returns the number
|
||||
* of arguments left that weren't recognized, which are also moved to the
|
||||
* head of the argument list. The last parameter is used in case no
|
||||
* parameter given by the first two arguments.
|
||||
*/
|
||||
int setup_revisions(int argc, const char **argv, struct rev_info *revs,
|
||||
struct setup_revision_opt *);
|
||||
|
||||
void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
|
||||
const struct option *options,
|
||||
const char * const usagestr[]);
|
||||
@ -319,9 +350,26 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
|
||||
int handle_revision_arg(const char *arg, struct rev_info *revs,
|
||||
int flags, unsigned revarg_opt);
|
||||
|
||||
/**
|
||||
* Reset the flags used by the revision walking api. You can use this to do
|
||||
* multiple sequential revision walks.
|
||||
*/
|
||||
void reset_revision_walk(void);
|
||||
|
||||
/**
|
||||
* Prepares the rev_info structure for a walk. You should check if it returns
|
||||
* any error (non-zero return code) and if it does not, you can start using
|
||||
* get_revision() to do the iteration.
|
||||
*/
|
||||
int prepare_revision_walk(struct rev_info *revs);
|
||||
|
||||
/**
|
||||
* Takes a pointer to a `rev_info` structure and iterates over it, returning a
|
||||
* `struct commit *` each time you call it. The end of the revision list is
|
||||
* indicated by returning a NULL pointer.
|
||||
*/
|
||||
struct commit *get_revision(struct rev_info *revs);
|
||||
|
||||
const char *get_revision_mark(const struct rev_info *revs,
|
||||
const struct commit *commit);
|
||||
void put_revision_mark(const struct rev_info *revs,
|
||||
@ -333,8 +381,19 @@ void mark_trees_uninteresting_sparse(struct repository *r, struct oidset *trees)
|
||||
|
||||
void show_object_with_name(FILE *, struct object *, const char *);
|
||||
|
||||
/**
|
||||
* This function can be used if you want to add commit objects as revision
|
||||
* information. You can use the `UNINTERESTING` object flag to indicate if
|
||||
* you want to include or exclude the given commit (and commits reachable
|
||||
* from the given commit) from the revision list.
|
||||
*
|
||||
* NOTE: If you have the commits as a string list then you probably want to
|
||||
* use setup_revisions(), instead of parsing each string and using this
|
||||
* function.
|
||||
*/
|
||||
void add_pending_object(struct rev_info *revs,
|
||||
struct object *obj, const char *name);
|
||||
|
||||
void add_pending_oid(struct rev_info *revs,
|
||||
const char *name, const struct object_id *oid,
|
||||
unsigned int flags);
|
||||
|
252
run-command.h
252
run-command.h
@ -5,8 +5,60 @@
|
||||
|
||||
#include "argv-array.h"
|
||||
|
||||
/**
|
||||
* The run-command API offers a versatile tool to run sub-processes with
|
||||
* redirected input and output as well as with a modified environment
|
||||
* and an alternate current directory.
|
||||
*
|
||||
* A similar API offers the capability to run a function asynchronously,
|
||||
* which is primarily used to capture the output that the function
|
||||
* produces in the caller in order to process it.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This describes the arguments, redirections, and environment of a
|
||||
* command to run in a sub-process.
|
||||
*
|
||||
* The caller:
|
||||
*
|
||||
* 1. allocates and clears (using child_process_init() or
|
||||
* CHILD_PROCESS_INIT) a struct child_process variable;
|
||||
* 2. initializes the members;
|
||||
* 3. calls start_command();
|
||||
* 4. processes the data;
|
||||
* 5. closes file descriptors (if necessary; see below);
|
||||
* 6. calls finish_command().
|
||||
*
|
||||
* Special forms of redirection are available by setting these members
|
||||
* to 1:
|
||||
*
|
||||
* .no_stdin, .no_stdout, .no_stderr: The respective channel is
|
||||
* redirected to /dev/null.
|
||||
*
|
||||
* .stdout_to_stderr: stdout of the child is redirected to its
|
||||
* stderr. This happens after stderr is itself redirected.
|
||||
* So stdout will follow stderr to wherever it is
|
||||
* redirected.
|
||||
*/
|
||||
struct child_process {
|
||||
|
||||
/**
|
||||
* The .argv member is set up as an array of string pointers (NULL
|
||||
* terminated), of which .argv[0] is the program name to run (usually
|
||||
* without a path). If the command to run is a git command, set argv[0] to
|
||||
* the command name without the 'git-' prefix and set .git_cmd = 1.
|
||||
*
|
||||
* Note that the ownership of the memory pointed to by .argv stays with the
|
||||
* caller, but it should survive until `finish_command` completes. If the
|
||||
* .argv member is NULL, `start_command` will point it at the .args
|
||||
* `argv_array` (so you may use one or the other, but you must use exactly
|
||||
* one). The memory in .args will be cleaned up automatically during
|
||||
* `finish_command` (or during `start_command` when it is unsuccessful).
|
||||
*
|
||||
*/
|
||||
const char **argv;
|
||||
|
||||
struct argv_array args;
|
||||
struct argv_array env_array;
|
||||
pid_t pid;
|
||||
@ -18,8 +70,8 @@ struct child_process {
|
||||
|
||||
/*
|
||||
* Using .in, .out, .err:
|
||||
* - Specify 0 for no redirections (child inherits stdin, stdout,
|
||||
* stderr from parent).
|
||||
* - Specify 0 for no redirections. No new file descriptor is allocated.
|
||||
* (child inherits stdin, stdout, stderr from parent).
|
||||
* - Specify -1 to have a pipe allocated as follows:
|
||||
* .in: returns the writable pipe end; parent writes to it,
|
||||
* the readable pipe end becomes child's stdin
|
||||
@ -37,13 +89,43 @@ struct child_process {
|
||||
int in;
|
||||
int out;
|
||||
int err;
|
||||
|
||||
/**
|
||||
* To specify a new initial working directory for the sub-process,
|
||||
* specify it in the .dir member.
|
||||
*/
|
||||
const char *dir;
|
||||
|
||||
/**
|
||||
* To modify the environment of the sub-process, specify an array of
|
||||
* string pointers (NULL terminated) in .env:
|
||||
*
|
||||
* - If the string is of the form "VAR=value", i.e. it contains '='
|
||||
* the variable is added to the child process's environment.
|
||||
*
|
||||
* - If the string does not contain '=', it names an environment
|
||||
* variable that will be removed from the child process's environment.
|
||||
*
|
||||
* If the .env member is NULL, `start_command` will point it at the
|
||||
* .env_array `argv_array` (so you may use one or the other, but not both).
|
||||
* The memory in .env_array will be cleaned up automatically during
|
||||
* `finish_command` (or during `start_command` when it is unsuccessful).
|
||||
*/
|
||||
const char *const *env;
|
||||
|
||||
unsigned no_stdin:1;
|
||||
unsigned no_stdout:1;
|
||||
unsigned no_stderr:1;
|
||||
unsigned git_cmd:1; /* if this is to be git sub-command */
|
||||
unsigned git_cmd:1; /* if this is to be git sub-command */
|
||||
|
||||
/**
|
||||
* If the program cannot be found, the functions return -1 and set
|
||||
* errno to ENOENT. Normally, an error message is printed, but if
|
||||
* .silent_exec_failure is set to 1, no message is printed for this
|
||||
* special error condition.
|
||||
*/
|
||||
unsigned silent_exec_failure:1;
|
||||
|
||||
unsigned stdout_to_stderr:1;
|
||||
unsigned use_shell:1;
|
||||
unsigned clean_on_exit:1;
|
||||
@ -53,13 +135,63 @@ struct child_process {
|
||||
};
|
||||
|
||||
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
|
||||
|
||||
/**
|
||||
* The functions: child_process_init, start_command, finish_command,
|
||||
* run_command, run_command_v_opt, run_command_v_opt_cd_env, child_process_clear
|
||||
* do the following:
|
||||
*
|
||||
* - If a system call failed, errno is set and -1 is returned. A diagnostic
|
||||
* is printed.
|
||||
*
|
||||
* - If the program was not found, then -1 is returned and errno is set to
|
||||
* ENOENT; a diagnostic is printed only if .silent_exec_failure is 0.
|
||||
*
|
||||
* - Otherwise, the program is run. If it terminates regularly, its exit
|
||||
* code is returned. No diagnostic is printed, even if the exit code is
|
||||
* non-zero.
|
||||
*
|
||||
* - If the program terminated due to a signal, then the return value is the
|
||||
* signal number + 128, ie. the same value that a POSIX shell's $? would
|
||||
* report. A diagnostic is printed.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a struct child_process variable.
|
||||
*/
|
||||
void child_process_init(struct child_process *);
|
||||
|
||||
/**
|
||||
* Release the memory associated with the struct child_process.
|
||||
* Most users of the run-command API don't need to call this
|
||||
* function explicitly because `start_command` invokes it on
|
||||
* failure and `finish_command` calls it automatically already.
|
||||
*/
|
||||
void child_process_clear(struct child_process *);
|
||||
|
||||
int is_executable(const char *name);
|
||||
|
||||
/**
|
||||
* Start a sub-process. Takes a pointer to a `struct child_process`
|
||||
* that specifies the details and returns pipe FDs (if requested).
|
||||
* See below for details.
|
||||
*/
|
||||
int start_command(struct child_process *);
|
||||
|
||||
/**
|
||||
* Wait for the completion of a sub-process that was started with
|
||||
* start_command().
|
||||
*/
|
||||
int finish_command(struct child_process *);
|
||||
|
||||
int finish_command_in_signal(struct child_process *);
|
||||
|
||||
/**
|
||||
* A convenience function that encapsulates a sequence of
|
||||
* start_command() followed by finish_command(). Takes a pointer
|
||||
* to a `struct child_process` that specifies the details.
|
||||
*/
|
||||
int run_command(struct child_process *);
|
||||
|
||||
/*
|
||||
@ -68,6 +200,20 @@ int run_command(struct child_process *);
|
||||
* overwritten by further calls to find_hook and run_hook_*.
|
||||
*/
|
||||
const char *find_hook(const char *name);
|
||||
|
||||
/**
|
||||
* Run a hook.
|
||||
* The first argument is a pathname to an index file, or NULL
|
||||
* if the hook uses the default index file or no index is needed.
|
||||
* The second argument is the name of the hook.
|
||||
* The further arguments correspond to the hook arguments.
|
||||
* The last argument has to be NULL to terminate the arguments list.
|
||||
* If the hook does not exist or is not executable, the return
|
||||
* value will be zero.
|
||||
* If it is executable, the hook will be executed and the exit
|
||||
* status of the hook is returned.
|
||||
* On execution, .stdout_to_stderr and .no_stdin will be set.
|
||||
*/
|
||||
LAST_ARG_MUST_BE_NULL
|
||||
int run_hook_le(const char *const *env, const char *name, ...);
|
||||
int run_hook_ve(const char *const *env, const char *name, va_list args);
|
||||
@ -78,6 +224,18 @@ int run_hook_ve(const char *const *env, const char *name, va_list args);
|
||||
#define RUN_SILENT_EXEC_FAILURE 8
|
||||
#define RUN_USING_SHELL 16
|
||||
#define RUN_CLEAN_ON_EXIT 32
|
||||
|
||||
/**
|
||||
* Convenience functions that encapsulate a sequence of
|
||||
* start_command() followed by finish_command(). The argument argv
|
||||
* specifies the program and its arguments. The argument opt is zero
|
||||
* or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`,
|
||||
* `RUN_COMMAND_STDOUT_TO_STDERR`, or `RUN_SILENT_EXEC_FAILURE`
|
||||
* that correspond to the members .no_stdin, .git_cmd,
|
||||
* .stdout_to_stderr, .silent_exec_failure of `struct child_process`.
|
||||
* The argument dir corresponds the member .dir. The argument env
|
||||
* corresponds to the member .env.
|
||||
*/
|
||||
int run_command_v_opt(const char **argv, int opt);
|
||||
int run_command_v_opt_tr2(const char **argv, int opt, const char *tr2_class);
|
||||
/*
|
||||
@ -125,15 +283,84 @@ static inline int capture_command(struct child_process *cmd,
|
||||
* It is expected that no synchronization and mutual exclusion between
|
||||
* the caller and the feed function is necessary so that the function
|
||||
* can run in a thread without interfering with the caller.
|
||||
*
|
||||
* The caller:
|
||||
*
|
||||
* 1. allocates and clears (memset(&asy, 0, sizeof(asy));) a
|
||||
* struct async variable;
|
||||
* 2. initializes .proc and .data;
|
||||
* 3. calls start_async();
|
||||
* 4. processes communicates with proc through .in and .out;
|
||||
* 5. closes .in and .out;
|
||||
* 6. calls finish_async().
|
||||
*
|
||||
* There are serious restrictions on what the asynchronous function can do
|
||||
* because this facility is implemented by a thread in the same address
|
||||
* space on most platforms (when pthreads is available), but by a pipe to
|
||||
* a forked process otherwise:
|
||||
*
|
||||
* - It cannot change the program's state (global variables, environment,
|
||||
* etc.) in a way that the caller notices; in other words, .in and .out
|
||||
* are the only communication channels to the caller.
|
||||
*
|
||||
* - It must not change the program's state that the caller of the
|
||||
* facility also uses.
|
||||
*
|
||||
*/
|
||||
struct async {
|
||||
/*
|
||||
* proc reads from in; closes it before return
|
||||
* proc writes to out; closes it before return
|
||||
* returns 0 on success, non-zero on failure
|
||||
|
||||
/**
|
||||
* The function pointer in .proc has the following signature:
|
||||
*
|
||||
* int proc(int in, int out, void *data);
|
||||
*
|
||||
* - in, out specifies a set of file descriptors to which the function
|
||||
* must read/write the data that it needs/produces. The function
|
||||
* *must* close these descriptors before it returns. A descriptor
|
||||
* may be -1 if the caller did not configure a descriptor for that
|
||||
* direction.
|
||||
*
|
||||
* - data is the value that the caller has specified in the .data member
|
||||
* of struct async.
|
||||
*
|
||||
* - The return value of the function is 0 on success and non-zero
|
||||
* on failure. If the function indicates failure, finish_async() will
|
||||
* report failure as well.
|
||||
*
|
||||
*/
|
||||
int (*proc)(int in, int out, void *data);
|
||||
|
||||
void *data;
|
||||
|
||||
/**
|
||||
* The members .in, .out are used to provide a set of fd's for
|
||||
* communication between the caller and the callee as follows:
|
||||
*
|
||||
* - Specify 0 to have no file descriptor passed. The callee will
|
||||
* receive -1 in the corresponding argument.
|
||||
*
|
||||
* - Specify < 0 to have a pipe allocated; start_async() replaces
|
||||
* with the pipe FD in the following way:
|
||||
*
|
||||
* .in: Returns the writable pipe end into which the caller
|
||||
* writes; the readable end of the pipe becomes the function's
|
||||
* in argument.
|
||||
*
|
||||
* .out: Returns the readable pipe end from which the caller
|
||||
* reads; the writable end of the pipe becomes the function's
|
||||
* out argument.
|
||||
*
|
||||
* The caller of start_async() must close the returned FDs after it
|
||||
* has completed reading from/writing from them.
|
||||
*
|
||||
* - Specify a file descriptor > 0 to be used by the function:
|
||||
*
|
||||
* .in: The FD must be readable; it becomes the function's in.
|
||||
* .out: The FD must be writable; it becomes the function's out.
|
||||
*
|
||||
* The specified FD is closed by start_async(), even if it fails to
|
||||
* run the function.
|
||||
*/
|
||||
int in; /* caller writes here and closes it */
|
||||
int out; /* caller reads from here and closes it */
|
||||
#ifdef NO_PTHREADS
|
||||
@ -146,8 +373,19 @@ struct async {
|
||||
int isolate_sigpipe;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a function asynchronously. Takes a pointer to a `struct
|
||||
* async` that specifies the details and returns a set of pipe FDs
|
||||
* for communication with the function. See below for details.
|
||||
*/
|
||||
int start_async(struct async *async);
|
||||
|
||||
/**
|
||||
* Wait for the completion of an asynchronous function that was
|
||||
* started with start_async().
|
||||
*/
|
||||
int finish_async(struct async *async);
|
||||
|
||||
int in_async(void);
|
||||
int async_with_fork(void);
|
||||
void check_pipe(int err);
|
||||
|
@ -48,7 +48,7 @@ int oid_array_for_each(struct oid_array *array,
|
||||
{
|
||||
int i;
|
||||
|
||||
/* No oid_array_sort() here! See the api-oid-array.txt docs! */
|
||||
/* No oid_array_sort() here! See sha1-array.h */
|
||||
|
||||
for (i = 0; i < array->nr; i++) {
|
||||
int ret = fn(array->oid + i, data);
|
||||
|
80
sha1-array.h
80
sha1-array.h
@ -1,6 +1,52 @@
|
||||
#ifndef SHA1_ARRAY_H
|
||||
#define SHA1_ARRAY_H
|
||||
|
||||
/**
|
||||
* The API provides storage and manipulation of sets of object identifiers.
|
||||
* The emphasis is on storage and processing efficiency, making them suitable
|
||||
* for large lists. Note that the ordering of items is not preserved over some
|
||||
* operations.
|
||||
*
|
||||
* Examples
|
||||
* --------
|
||||
* -----------------------------------------
|
||||
* int print_callback(const struct object_id *oid,
|
||||
* void *data)
|
||||
* {
|
||||
* printf("%s\n", oid_to_hex(oid));
|
||||
* return 0; // always continue
|
||||
* }
|
||||
*
|
||||
* void some_func(void)
|
||||
* {
|
||||
* struct sha1_array hashes = OID_ARRAY_INIT;
|
||||
* struct object_id oid;
|
||||
*
|
||||
* // Read objects into our set
|
||||
* while (read_object_from_stdin(oid.hash))
|
||||
* oid_array_append(&hashes, &oid);
|
||||
*
|
||||
* // Check if some objects are in our set
|
||||
* while (read_object_from_stdin(oid.hash)) {
|
||||
* if (oid_array_lookup(&hashes, &oid) >= 0)
|
||||
* printf("it's in there!\n");
|
||||
*
|
||||
* // Print the unique set of objects. We could also have
|
||||
* // avoided adding duplicate objects in the first place,
|
||||
* // but we would end up re-sorting the array repeatedly.
|
||||
* // Instead, this will sort once and then skip duplicates
|
||||
* // in linear time.
|
||||
*
|
||||
* oid_array_for_each_unique(&hashes, print_callback, NULL);
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* A single array of object IDs. This should be initialized by assignment from
|
||||
* `OID_ARRAY_INIT`. The `oid` member contains the actual data. The `nr` member
|
||||
* contains the number of items in the set. The `alloc` and `sorted` members
|
||||
* are used internally, and should not be needed by API callers.
|
||||
*/
|
||||
struct oid_array {
|
||||
struct object_id *oid;
|
||||
int nr;
|
||||
@ -10,18 +56,52 @@ struct oid_array {
|
||||
|
||||
#define OID_ARRAY_INIT { NULL, 0, 0, 0 }
|
||||
|
||||
/**
|
||||
* Add an item to the set. The object ID will be placed at the end of the array
|
||||
* (but note that some operations below may lose this ordering).
|
||||
*/
|
||||
void oid_array_append(struct oid_array *array, const struct object_id *oid);
|
||||
|
||||
/**
|
||||
* Perform a binary search of the array for a specific object ID. If found,
|
||||
* returns the offset (in number of elements) of the object ID. If not found,
|
||||
* returns a negative integer. If the array is not sorted, this function has
|
||||
* the side effect of sorting it.
|
||||
*/
|
||||
int oid_array_lookup(struct oid_array *array, const struct object_id *oid);
|
||||
|
||||
/**
|
||||
* Free all memory associated with the array and return it to the initial,
|
||||
* empty state.
|
||||
*/
|
||||
void oid_array_clear(struct oid_array *array);
|
||||
|
||||
typedef int (*for_each_oid_fn)(const struct object_id *oid,
|
||||
void *data);
|
||||
/**
|
||||
* Iterate over each element of the list, executing the callback function for
|
||||
* each one. Does not sort the list, so any custom hash order is retained.
|
||||
* If the callback returns a non-zero value, the iteration ends immediately
|
||||
* and the callback's return is propagated; otherwise, 0 is returned.
|
||||
*/
|
||||
int oid_array_for_each(struct oid_array *array,
|
||||
for_each_oid_fn fn,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* Iterate over each unique element of the list in sorted order, but otherwise
|
||||
* behave like `oid_array_for_each`. If the array is not sorted, this function
|
||||
* has the side effect of sorting it.
|
||||
*/
|
||||
int oid_array_for_each_unique(struct oid_array *array,
|
||||
for_each_oid_fn fn,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* Apply the callback function `want` to each entry in the array, retaining
|
||||
* only the entries for which the function returns true. Preserve the order
|
||||
* of the entries that are retained.
|
||||
*/
|
||||
void oid_array_filter(struct oid_array *array,
|
||||
for_each_oid_fn want,
|
||||
void *cbdata);
|
||||
|
45
sigchain.h
45
sigchain.h
@ -1,12 +1,57 @@
|
||||
#ifndef SIGCHAIN_H
|
||||
#define SIGCHAIN_H
|
||||
|
||||
/**
|
||||
* Code often wants to set a signal handler to clean up temporary files or
|
||||
* other work-in-progress when we die unexpectedly. For multiple pieces of
|
||||
* code to do this without conflicting, each piece of code must remember
|
||||
* the old value of the handler and restore it either when:
|
||||
*
|
||||
* 1. The work-in-progress is finished, and the handler is no longer
|
||||
* necessary. The handler should revert to the original behavior
|
||||
* (either another handler, SIG_DFL, or SIG_IGN).
|
||||
*
|
||||
* 2. The signal is received. We should then do our cleanup, then chain
|
||||
* to the next handler (or die if it is SIG_DFL).
|
||||
*
|
||||
* Sigchain is a tiny library for keeping a stack of handlers. Your handler
|
||||
* and installation code should look something like:
|
||||
*
|
||||
* ------------------------------------------
|
||||
* void clean_foo_on_signal(int sig)
|
||||
* {
|
||||
* clean_foo();
|
||||
* sigchain_pop(sig);
|
||||
* raise(sig);
|
||||
* }
|
||||
*
|
||||
* void other_func()
|
||||
* {
|
||||
* sigchain_push_common(clean_foo_on_signal);
|
||||
* mess_up_foo();
|
||||
* clean_foo();
|
||||
* }
|
||||
* ------------------------------------------
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handlers are given the typedef of sigchain_fun. This is the same type
|
||||
* that is given to signal() or sigaction(). It is perfectly reasonable to
|
||||
* push SIG_DFL or SIG_IGN onto the stack.
|
||||
*/
|
||||
typedef void (*sigchain_fun)(int);
|
||||
|
||||
/* You can sigchain_push and sigchain_pop individual signals. */
|
||||
int sigchain_push(int sig, sigchain_fun f);
|
||||
int sigchain_pop(int sig);
|
||||
|
||||
/**
|
||||
* push the handler onto the stack for the common signals:
|
||||
* SIGINT, SIGHUP, SIGTERM, SIGQUIT and SIGPIPE.
|
||||
*/
|
||||
void sigchain_push_common(sigchain_fun f);
|
||||
|
||||
void sigchain_pop_common(void);
|
||||
|
||||
#endif /* SIGCHAIN_H */
|
||||
|
@ -7,9 +7,31 @@
|
||||
#include "submodule.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/**
|
||||
* The submodule config cache API allows to read submodule
|
||||
* configurations/information from specified revisions. Internally
|
||||
* information is lazily read into a cache that is used to avoid
|
||||
* unnecessary parsing of the same .gitmodules files. Lookups can be done by
|
||||
* submodule path or name.
|
||||
*
|
||||
* Usage
|
||||
* -----
|
||||
*
|
||||
* The caller can look up information about submodules by using the
|
||||
* `submodule_from_path()` or `submodule_from_name()` functions. They return
|
||||
* a `struct submodule` which contains the values. The API automatically
|
||||
* initializes and allocates the needed infrastructure on-demand. If the
|
||||
* caller does only want to lookup values from revisions the initialization
|
||||
* can be skipped.
|
||||
*
|
||||
* If the internal cache might grow too big or when the caller is done with
|
||||
* the API, all internally cached values can be freed with submodule_free().
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Submodule entry containing the information about a certain submodule
|
||||
* in a certain revision.
|
||||
* in a certain revision. It is returned by the lookup functions.
|
||||
*/
|
||||
struct submodule {
|
||||
const char *path;
|
||||
@ -41,13 +63,27 @@ int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
|
||||
int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
|
||||
void repo_read_gitmodules(struct repository *repo);
|
||||
void gitmodules_config_oid(const struct object_id *commit_oid);
|
||||
|
||||
/**
|
||||
* Same as submodule_from_path but lookup by name.
|
||||
*/
|
||||
const struct submodule *submodule_from_name(struct repository *r,
|
||||
const struct object_id *commit_or_tree,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Given a tree-ish in the superproject and a path, return the submodule that
|
||||
* is bound at the path in the named tree.
|
||||
*/
|
||||
const struct submodule *submodule_from_path(struct repository *r,
|
||||
const struct object_id *commit_or_tree,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Use these to free the internally cached values.
|
||||
*/
|
||||
void submodule_free(struct repository *r);
|
||||
|
||||
int print_config_from_gitmodules(struct repository *repo, const char *key);
|
||||
int config_set_in_gitmodules_file_gently(const char *key, const char *value);
|
||||
|
||||
|
133
trace.h
133
trace.h
@ -4,6 +4,82 @@
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/**
|
||||
* The trace API can be used to print debug messages to stderr or a file. Trace
|
||||
* code is inactive unless explicitly enabled by setting `GIT_TRACE*` environment
|
||||
* variables.
|
||||
*
|
||||
* The trace implementation automatically adds `timestamp file:line ... \n` to
|
||||
* all trace messages. E.g.:
|
||||
*
|
||||
* ------------
|
||||
* 23:59:59.123456 git.c:312 trace: built-in: git 'foo'
|
||||
* 00:00:00.000001 builtin/foo.c:99 foo: some message
|
||||
* ------------
|
||||
*
|
||||
* Bugs & Caveats
|
||||
* --------------
|
||||
*
|
||||
* GIT_TRACE_* environment variables can be used to tell Git to show
|
||||
* trace output to its standard error stream. Git can often spawn a pager
|
||||
* internally to run its subcommand and send its standard output and
|
||||
* standard error to it.
|
||||
*
|
||||
* Because GIT_TRACE_PERFORMANCE trace is generated only at the very end
|
||||
* of the program with atexit(), which happens after the pager exits, it
|
||||
* would not work well if you send its log to the standard error output
|
||||
* and let Git spawn the pager at the same time.
|
||||
*
|
||||
* As a work around, you can for example use '--no-pager', or set
|
||||
* GIT_TRACE_PERFORMANCE to another file descriptor which is redirected
|
||||
* to stderr, or set GIT_TRACE_PERFORMANCE to a file specified by its
|
||||
* absolute path.
|
||||
*
|
||||
* For example instead of the following command which by default may not
|
||||
* print any performance information:
|
||||
*
|
||||
* ------------
|
||||
* GIT_TRACE_PERFORMANCE=2 git log -1
|
||||
* ------------
|
||||
*
|
||||
* you may want to use:
|
||||
*
|
||||
* ------------
|
||||
* GIT_TRACE_PERFORMANCE=2 git --no-pager log -1
|
||||
* ------------
|
||||
*
|
||||
* or:
|
||||
*
|
||||
* ------------
|
||||
* GIT_TRACE_PERFORMANCE=3 3>&2 git log -1
|
||||
* ------------
|
||||
*
|
||||
* or:
|
||||
*
|
||||
* ------------
|
||||
* GIT_TRACE_PERFORMANCE=/path/to/log/file git log -1
|
||||
* ------------
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines a trace key (or category). The default (for API functions that
|
||||
* don't take a key) is `GIT_TRACE`.
|
||||
*
|
||||
* E.g. to define a trace key controlled by environment variable `GIT_TRACE_FOO`:
|
||||
*
|
||||
* ------------
|
||||
* static struct trace_key trace_foo = TRACE_KEY_INIT(FOO);
|
||||
*
|
||||
* static void trace_print_foo(const char *message)
|
||||
* {
|
||||
* trace_printf_key(&trace_foo, "%s", message);
|
||||
* }
|
||||
* ------------
|
||||
*
|
||||
* Note: don't use `const` as the trace implementation stores internal state in
|
||||
* the `trace_key` structure.
|
||||
*/
|
||||
struct trace_key {
|
||||
const char * const key;
|
||||
int fd;
|
||||
@ -18,31 +94,84 @@ extern struct trace_key trace_perf_key;
|
||||
extern struct trace_key trace_setup_key;
|
||||
|
||||
void trace_repo_setup(const char *prefix);
|
||||
|
||||
/**
|
||||
* Checks whether the trace key is enabled. Used to prevent expensive
|
||||
* string formatting before calling one of the printing APIs.
|
||||
*/
|
||||
int trace_want(struct trace_key *key);
|
||||
|
||||
/**
|
||||
* Disables tracing for the specified key, even if the environment variable
|
||||
* was set.
|
||||
*/
|
||||
void trace_disable(struct trace_key *key);
|
||||
|
||||
/**
|
||||
* Returns nanoseconds since the epoch (01/01/1970), typically used
|
||||
* for performance measurements.
|
||||
* Currently there are high precision timer implementations for Linux (using
|
||||
* `clock_gettime(CLOCK_MONOTONIC)`) and Windows (`QueryPerformanceCounter`).
|
||||
* Other platforms use `gettimeofday` as time source.
|
||||
*/
|
||||
uint64_t getnanotime(void);
|
||||
|
||||
void trace_command_performance(const char **argv);
|
||||
void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);
|
||||
uint64_t trace_performance_enter(void);
|
||||
|
||||
#ifndef HAVE_VARIADIC_MACROS
|
||||
|
||||
/**
|
||||
* Prints a formatted message, similar to printf.
|
||||
*/
|
||||
__attribute__((format (printf, 1, 2)))
|
||||
void trace_printf(const char *format, ...);
|
||||
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
void trace_printf_key(struct trace_key *key, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Prints a formatted message, followed by a quoted list of arguments.
|
||||
*/
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
void trace_argv_printf(const char **argv, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Prints the strbuf, without additional formatting (i.e. doesn't
|
||||
* choke on `%` or even `\0`).
|
||||
*/
|
||||
void trace_strbuf(struct trace_key *key, const struct strbuf *data);
|
||||
|
||||
/* Prints elapsed time (in nanoseconds) if GIT_TRACE_PERFORMANCE is enabled. */
|
||||
/**
|
||||
* Prints elapsed time (in nanoseconds) if GIT_TRACE_PERFORMANCE is enabled.
|
||||
*
|
||||
* Example:
|
||||
* ------------
|
||||
* uint64_t t = 0;
|
||||
* for (;;) {
|
||||
* // ignore
|
||||
* t -= getnanotime();
|
||||
* // code section to measure
|
||||
* t += getnanotime();
|
||||
* // ignore
|
||||
* }
|
||||
* trace_performance(t, "frotz");
|
||||
* ------------
|
||||
*/
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
void trace_performance(uint64_t nanos, const char *format, ...);
|
||||
|
||||
/* Prints elapsed time since 'start' if GIT_TRACE_PERFORMANCE is enabled. */
|
||||
/**
|
||||
* Prints elapsed time since 'start' if GIT_TRACE_PERFORMANCE is enabled.
|
||||
*
|
||||
* Example:
|
||||
* ------------
|
||||
* uint64_t start = getnanotime();
|
||||
* // code section to measure
|
||||
* trace_performance_since(start, "foobar");
|
||||
* ------------
|
||||
*/
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
void trace_performance_since(uint64_t start, const char *format, ...);
|
||||
|
||||
|
124
trace2.h
124
trace2.h
@ -1,6 +1,40 @@
|
||||
#ifndef TRACE2_H
|
||||
#define TRACE2_H
|
||||
|
||||
/**
|
||||
* The Trace2 API can be used to print debug, performance, and telemetry
|
||||
* information to stderr or a file. The Trace2 feature is inactive unless
|
||||
* explicitly enabled by enabling one or more Trace2 Targets.
|
||||
*
|
||||
* The Trace2 API is intended to replace the existing (Trace1)
|
||||
* printf-style tracing provided by the existing `GIT_TRACE` and
|
||||
* `GIT_TRACE_PERFORMANCE` facilities. During initial implementation,
|
||||
* Trace2 and Trace1 may operate in parallel.
|
||||
*
|
||||
* The Trace2 API defines a set of high-level messages with known fields,
|
||||
* such as (`start`: `argv`) and (`exit`: {`exit-code`, `elapsed-time`}).
|
||||
*
|
||||
* Trace2 instrumentation throughout the Git code base sends Trace2
|
||||
* messages to the enabled Trace2 Targets. Targets transform these
|
||||
* messages content into purpose-specific formats and write events to
|
||||
* their data streams. In this manner, the Trace2 API can drive
|
||||
* many different types of analysis.
|
||||
*
|
||||
* Targets are defined using a VTable allowing easy extension to other
|
||||
* formats in the future. This might be used to define a binary format,
|
||||
* for example.
|
||||
*
|
||||
* Trace2 is controlled using `trace2.*` config values in the system and
|
||||
* global config files and `GIT_TRACE2*` environment variables. Trace2 does
|
||||
* not read from repo local or worktree config files or respect `-c`
|
||||
* command line config settings.
|
||||
*
|
||||
* For more info about: trace2 targets, conventions for public functions and
|
||||
* macros, trace2 target formats and examples on trace2 API usage refer to
|
||||
* Documentation/technical/api-trace2.txt
|
||||
*
|
||||
*/
|
||||
|
||||
struct child_process;
|
||||
struct repository;
|
||||
struct json_writer;
|
||||
@ -39,7 +73,12 @@ void trace2_initialize_clock(void);
|
||||
/*
|
||||
* Initialize TRACE2 tracing facility if any of the builtin TRACE2
|
||||
* targets are enabled in the system config or the environment.
|
||||
* Emits a 'version' event.
|
||||
* This includes setting up the Trace2 thread local storage (TLS).
|
||||
* Emits a 'version' message containing the version of git
|
||||
* and the Trace2 protocol.
|
||||
*
|
||||
* This function should be called from `main()` as early as possible in
|
||||
* the life of the process after essential process initialization.
|
||||
*
|
||||
* Cleanup/Termination is handled automatically by a registered
|
||||
* atexit() routine.
|
||||
@ -49,7 +88,7 @@ void trace2_initialize_fl(const char *file, int line);
|
||||
#define trace2_initialize() trace2_initialize_fl(__FILE__, __LINE__)
|
||||
|
||||
/*
|
||||
* Return true if trace2 is enabled.
|
||||
* Return 1 if trace2 is enabled (at least one target is active).
|
||||
*/
|
||||
int trace2_is_enabled(void);
|
||||
|
||||
@ -114,7 +153,8 @@ void trace2_cmd_mode_fl(const char *file, int line, const char *mode);
|
||||
#define trace2_cmd_mode(sv) trace2_cmd_mode_fl(__FILE__, __LINE__, (sv))
|
||||
|
||||
/*
|
||||
* Emit an 'alias' expansion event.
|
||||
* Emits an "alias" message containing the alias used and the argument
|
||||
* expansion.
|
||||
*/
|
||||
void trace2_cmd_alias_fl(const char *file, int line, const char *alias,
|
||||
const char **argv);
|
||||
@ -123,7 +163,7 @@ void trace2_cmd_alias_fl(const char *file, int line, const char *alias,
|
||||
trace2_cmd_alias_fl(__FILE__, __LINE__, (alias), (argv))
|
||||
|
||||
/*
|
||||
* Emit one or more 'def_param' events for "interesting" configuration
|
||||
* Emit one or more 'def_param' events for "important" configuration
|
||||
* settings.
|
||||
*
|
||||
* Use the TR2_SYSENV_CFG_PARAM setting to register a comma-separated
|
||||
@ -144,7 +184,7 @@ void trace2_cmd_list_config_fl(const char *file, int line);
|
||||
|
||||
/*
|
||||
* Emit a "def_param" event for the given config key/value pair IF
|
||||
* we consider the key to be "interesting".
|
||||
* we consider the key to be "important".
|
||||
*
|
||||
* Use this for new/updated config settings created/updated after
|
||||
* trace2_cmd_list_config() is called.
|
||||
@ -155,20 +195,34 @@ void trace2_cmd_set_config_fl(const char *file, int line, const char *key,
|
||||
#define trace2_cmd_set_config(k, v) \
|
||||
trace2_cmd_set_config_fl(__FILE__, __LINE__, (k), (v))
|
||||
|
||||
/*
|
||||
* Emit a 'child_start' event prior to spawning a child process.
|
||||
/**
|
||||
* Emits a "child_start" message containing the "child-id",
|
||||
* "child-argv", and "child-classification".
|
||||
*
|
||||
* Before calling optionally set "cmd->trace2_child_class" to a string
|
||||
* describing the type of the child process. For example, "editor" or
|
||||
* "pager".
|
||||
*
|
||||
* This function assigns a unique "child-id" to `cmd->trace2_child_id`.
|
||||
* This field is used later during the "child_exit" message to associate
|
||||
* it with the "child_start" message.
|
||||
*
|
||||
* This function should be called before spawning the child process.
|
||||
*/
|
||||
void trace2_child_start_fl(const char *file, int line,
|
||||
struct child_process *cmd);
|
||||
|
||||
#define trace2_child_start(cmd) trace2_child_start_fl(__FILE__, __LINE__, (cmd))
|
||||
|
||||
/*
|
||||
* Emit a 'child_exit' event after the child process completes.
|
||||
/**
|
||||
* Emits a "child_exit" message containing the "child-id",
|
||||
* the child's elapsed time and exit-code.
|
||||
*
|
||||
* The reported elapsed time includes the process creation overhead and
|
||||
* time spend waiting for it to exit, so it may be slightly longer than
|
||||
* the time reported by the child itself.
|
||||
*
|
||||
* This function should be called after reaping the child process.
|
||||
*/
|
||||
void trace2_child_exit_fl(const char *file, int line, struct child_process *cmd,
|
||||
int child_exit_code);
|
||||
@ -176,21 +230,22 @@ void trace2_child_exit_fl(const char *file, int line, struct child_process *cmd,
|
||||
#define trace2_child_exit(cmd, code) \
|
||||
trace2_child_exit_fl(__FILE__, __LINE__, (cmd), (code))
|
||||
|
||||
/*
|
||||
/**
|
||||
* Emit an 'exec' event prior to calling one of exec(), execv(),
|
||||
* execvp(), and etc. On Unix-derived systems, this will be the
|
||||
* last event emitted for the current process, unless the exec
|
||||
* fails. On Windows, exec() behaves like 'child_start' and a
|
||||
* waitpid(), so additional events may be emitted.
|
||||
*
|
||||
* Returns the "exec_id".
|
||||
* Returns a unique "exec-id". This value is used later
|
||||
* if the exec() fails and a "exec-result" message is necessary.
|
||||
*/
|
||||
int trace2_exec_fl(const char *file, int line, const char *exe,
|
||||
const char **argv);
|
||||
|
||||
#define trace2_exec(exe, argv) trace2_exec_fl(__FILE__, __LINE__, (exe), (argv))
|
||||
|
||||
/*
|
||||
/**
|
||||
* Emit an 'exec_result' when possible. On Unix-derived systems,
|
||||
* this should be called after exec() returns (which only happens
|
||||
* when there is an error starting the new process). On Windows,
|
||||
@ -226,11 +281,12 @@ void trace2_thread_exit_fl(const char *file, int line);
|
||||
#define trace2_thread_exit() trace2_thread_exit_fl(__FILE__, __LINE__)
|
||||
|
||||
/*
|
||||
* Emit a 'param' event.
|
||||
* Emits a "def_param" message containing a key/value pair.
|
||||
*
|
||||
* Write a "<param> = <value>" pair describing some aspect of the
|
||||
* run such as an important configuration setting or command line
|
||||
* option that significantly changes command behavior.
|
||||
* This message is intended to report some global aspect of the current
|
||||
* command, such as a configuration setting or command line switch that
|
||||
* significantly affects program performance or behavior, such as
|
||||
* `core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`.
|
||||
*/
|
||||
void trace2_def_param_fl(const char *file, int line, const char *param,
|
||||
const char *value);
|
||||
@ -243,18 +299,35 @@ void trace2_def_param_fl(const char *file, int line, const char *param,
|
||||
* a trace2-repo-id to be used in subsequent activity events.
|
||||
*
|
||||
* Emits a 'worktree' event for this repo instance.
|
||||
*
|
||||
* Region and data messages may refer to this repo-id.
|
||||
*
|
||||
* The main/top-level repository will have repo-id value 1 (aka "r1").
|
||||
*
|
||||
* The repo-id field is in anticipation of future in-proc submodule
|
||||
* repositories.
|
||||
*/
|
||||
void trace2_def_repo_fl(const char *file, int line, struct repository *repo);
|
||||
|
||||
#define trace2_def_repo(repo) trace2_def_repo_fl(__FILE__, __LINE__, repo)
|
||||
|
||||
/*
|
||||
/**
|
||||
* Emit a 'region_enter' event for <category>.<label> with optional
|
||||
* repo-id and printf message.
|
||||
*
|
||||
* Enter a new nesting level on the current thread and remember the
|
||||
* current time. This controls the indenting of all subsequent events
|
||||
* on this thread.
|
||||
* This function pushes a new region nesting stack level on the current
|
||||
* thread and starts a clock for the new stack frame.
|
||||
*
|
||||
* The `category` field is an arbitrary category name used to classify
|
||||
* regions by feature area, such as "status" or "index". At this time
|
||||
* it is only just printed along with the rest of the message. It may
|
||||
* be used in the future to filter messages.
|
||||
*
|
||||
* The `label` field is an arbitrary label used to describe the activity
|
||||
* being started, such as "read_recursive" or "do_read_index".
|
||||
*
|
||||
* The `repo` field, if set, will be used to get the "repo-id", so that
|
||||
* recursive oerations can be attributed to the correct repository.
|
||||
*/
|
||||
void trace2_region_enter_fl(const char *file, int line, const char *category,
|
||||
const char *label, const struct repository *repo, ...);
|
||||
@ -289,12 +362,17 @@ void trace2_region_enter_printf(const char *category, const char *label,
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
/*
|
||||
/**
|
||||
* Emit a 'region_leave' event for <category>.<label> with optional
|
||||
* repo-id and printf message.
|
||||
*
|
||||
* Leave current nesting level and report the elapsed time spent
|
||||
* in this nesting level.
|
||||
*
|
||||
* The `category`, `label`, and `repo` fields are the same as
|
||||
* trace2_region_enter_fl. The `category` and `label` do not
|
||||
* need to match the corresponding "region_enter" message,
|
||||
* but it makes the data stream easier to understand.
|
||||
*/
|
||||
void trace2_region_leave_fl(const char *file, int line, const char *category,
|
||||
const char *label, const struct repository *repo, ...);
|
||||
@ -329,10 +407,12 @@ void trace2_region_leave_printf(const char *category, const char *label,
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
/*
|
||||
/**
|
||||
* Emit a key-value pair 'data' event of the form <category>.<key> = <value>.
|
||||
* This event implicitly contains information about thread, nesting region,
|
||||
* and optional repo-id.
|
||||
* This could be used to print the number of files in a directory during
|
||||
* a multi-threaded recursive tree walk.
|
||||
*
|
||||
* On event-based TRACE2 targets, this generates a 'data' event suitable
|
||||
* for post-processing. On printf-based TRACE2 targets, this is converted
|
||||
|
122
tree-walk.h
122
tree-walk.h
@ -3,6 +3,13 @@
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
/**
|
||||
* The tree walking API is used to traverse and inspect trees.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An entry in a tree. Each entry has a sha1 identifier, pathname, and mode.
|
||||
*/
|
||||
struct name_entry {
|
||||
struct object_id oid;
|
||||
const char *path;
|
||||
@ -10,12 +17,29 @@ struct name_entry {
|
||||
unsigned int mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* A semi-opaque data structure used to maintain the current state of the walk.
|
||||
*/
|
||||
struct tree_desc {
|
||||
/*
|
||||
* pointer into the memory representation of the tree. It always
|
||||
* points at the current entry being visited.
|
||||
*/
|
||||
const void *buffer;
|
||||
|
||||
/* points to the current entry being visited. */
|
||||
struct name_entry entry;
|
||||
|
||||
/* counts the number of bytes left in the `buffer`. */
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the entry currently being visited (the one pointed to by
|
||||
* `tree_desc's` `entry` member) and return the sha1 of the entry. The
|
||||
* `pathp` and `modep` arguments are set to the entry's pathname and mode
|
||||
* respectively.
|
||||
*/
|
||||
static inline const struct object_id *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned short *modep)
|
||||
{
|
||||
*pathp = desc->entry.path;
|
||||
@ -23,6 +47,11 @@ static inline const struct object_id *tree_entry_extract(struct tree_desc *desc,
|
||||
return &desc->entry.oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of a tree entry's pathname. This utilizes the
|
||||
* memory structure of a tree entry to avoid the overhead of using a
|
||||
* generic strlen().
|
||||
*/
|
||||
static inline int tree_entry_len(const struct name_entry *ne)
|
||||
{
|
||||
return ne->pathlen;
|
||||
@ -33,52 +62,141 @@ static inline int tree_entry_len(const struct name_entry *ne)
|
||||
* corrupt tree entry rather than dying,
|
||||
*/
|
||||
|
||||
/**
|
||||
* Walk to the next entry in a tree. This is commonly used in conjunction
|
||||
* with `tree_entry_extract` to inspect the current entry.
|
||||
*/
|
||||
void update_tree_entry(struct tree_desc *);
|
||||
|
||||
int update_tree_entry_gently(struct tree_desc *);
|
||||
|
||||
/**
|
||||
* Initialize a `tree_desc` and decode its first entry. The buffer and
|
||||
* size parameters are assumed to be the same as the buffer and size
|
||||
* members of `struct tree`.
|
||||
*/
|
||||
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
|
||||
|
||||
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size);
|
||||
|
||||
/*
|
||||
* Helper function that does both tree_entry_extract() and update_tree_entry()
|
||||
* and returns true for success
|
||||
* Visit the next entry in a tree. Returns 1 when there are more entries
|
||||
* left to visit and 0 when all entries have been visited. This is
|
||||
* commonly used in the test of a while loop.
|
||||
*/
|
||||
int tree_entry(struct tree_desc *, struct name_entry *);
|
||||
|
||||
int tree_entry_gently(struct tree_desc *, struct name_entry *);
|
||||
|
||||
/**
|
||||
* Initialize a `tree_desc` and decode its first entry given the
|
||||
* object ID of a tree. Returns the `buffer` member if the latter
|
||||
* is a valid tree identifier and NULL otherwise.
|
||||
*/
|
||||
void *fill_tree_descriptor(struct repository *r,
|
||||
struct tree_desc *desc,
|
||||
const struct object_id *oid);
|
||||
|
||||
struct traverse_info;
|
||||
typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);
|
||||
|
||||
/**
|
||||
* Traverse `n` number of trees in parallel. The `fn` callback member of
|
||||
* `traverse_info` is called once for each tree entry.
|
||||
*/
|
||||
int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);
|
||||
|
||||
enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned short *mode);
|
||||
|
||||
/**
|
||||
* A structure used to maintain the state of a traversal.
|
||||
*/
|
||||
struct traverse_info {
|
||||
const char *traverse_path;
|
||||
|
||||
/*
|
||||
* points to the traverse_info which was used to descend into the
|
||||
* current tree. If this is the top-level tree `prev` will point to
|
||||
* a dummy traverse_info.
|
||||
*/
|
||||
struct traverse_info *prev;
|
||||
|
||||
/* is the entry for the current tree (if the tree is a subtree). */
|
||||
const char *name;
|
||||
|
||||
size_t namelen;
|
||||
unsigned mode;
|
||||
|
||||
/* is the length of the full path for the current tree. */
|
||||
size_t pathlen;
|
||||
|
||||
struct pathspec *pathspec;
|
||||
|
||||
/* can be used by callbacks to maintain directory-file conflicts. */
|
||||
unsigned long df_conflicts;
|
||||
|
||||
/* a callback called for each entry in the tree.
|
||||
*
|
||||
* The arguments passed to the traverse callback are as follows:
|
||||
*
|
||||
* - `n` counts the number of trees being traversed.
|
||||
*
|
||||
* - `mask` has its nth bit set if something exists in the nth entry.
|
||||
*
|
||||
* - `dirmask` has its nth bit set if the nth tree's entry is a directory.
|
||||
*
|
||||
* - `entry` is an array of size `n` where the nth entry is from the nth tree.
|
||||
*
|
||||
* - `info` maintains the state of the traversal.
|
||||
*
|
||||
* Returning a negative value will terminate the traversal. Otherwise the
|
||||
* return value is treated as an update mask. If the nth bit is set the nth tree
|
||||
* will be updated and if the bit is not set the nth tree entry will be the
|
||||
* same in the next callback invocation.
|
||||
*/
|
||||
traverse_callback_t fn;
|
||||
|
||||
/* can be anything the `fn` callback would want to use. */
|
||||
void *data;
|
||||
|
||||
/* tells whether to stop at the first error or not. */
|
||||
int show_all_errors;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find an entry in a tree given a pathname and the sha1 of a tree to
|
||||
* search. Returns 0 if the entry is found and -1 otherwise. The third
|
||||
* and fourth parameters are set to the entry's sha1 and mode respectively.
|
||||
*/
|
||||
int get_tree_entry(struct repository *, const struct object_id *, const char *, struct object_id *, unsigned short *);
|
||||
|
||||
/**
|
||||
* Generate the full pathname of a tree entry based from the root of the
|
||||
* traversal. For example, if the traversal has recursed into another
|
||||
* tree named "bar" the pathname of an entry "baz" in the "bar"
|
||||
* tree would be "bar/baz".
|
||||
*/
|
||||
char *make_traverse_path(char *path, size_t pathlen, const struct traverse_info *info,
|
||||
const char *name, size_t namelen);
|
||||
|
||||
/**
|
||||
* Convenience wrapper to `make_traverse_path` into a strbuf.
|
||||
*/
|
||||
void strbuf_make_traverse_path(struct strbuf *out,
|
||||
const struct traverse_info *info,
|
||||
const char *name, size_t namelen);
|
||||
|
||||
/**
|
||||
* Initialize a `traverse_info` given the pathname of the tree to start
|
||||
* traversing from.
|
||||
*/
|
||||
void setup_traverse_info(struct traverse_info *info, const char *base);
|
||||
|
||||
/**
|
||||
* Calculate the length of a pathname returned by `make_traverse_path`.
|
||||
* This utilizes the memory structure of a tree entry to avoid the
|
||||
* overhead of using a generic strlen().
|
||||
*/
|
||||
static inline size_t traverse_path_len(const struct traverse_info *info,
|
||||
size_t namelen)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user