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.hmaint
						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 | - `Documentation/user-manual.txt` under "Hacking Git" contains some coverage of | ||||||
|   the revision walker in its various incarnations. |   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] | - 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 |   gives a good overview of the types of objects in Git and what your object | ||||||
|   walk is really describing. |   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. | `nr` represents the number of `rev_cmdline_entry` present in the array. | ||||||
|  |  | ||||||
| `alloc` is used by the `ALLOC_GROW` macro. Check | `alloc` is used by the `ALLOC_GROW` macro. Check `cache.h` - this variable is | ||||||
| `Documentation/technical/api-allocation-growing.txt` - this variable is used to | used to track the allocated size of the list. | ||||||
| track the allocated size of the list. |  | ||||||
|  |  | ||||||
| Per entry, we find: | 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 | usernames and passwords. The git-credential command exposes this | ||||||
| interface to scripts which may want to retrieve, store, or prompt for | interface to scripts which may want to retrieve, store, or prompt for | ||||||
| credentials in the same manner as Git. The design of this scriptable | credentials in the same manner as Git. The design of this scriptable | ||||||
| interface models the internal C API; see | interface models the internal C API; see credential.h for more | ||||||
| link:technical/api-credentials.html[the Git credential API] for more |  | ||||||
| background on the concepts. | background on the concepts. | ||||||
|  |  | ||||||
| git-credential takes an "action" option on the command-line (one of | 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 | You can write your own custom helpers to interface with any system in | ||||||
| which you keep credentials. See the documentation for Git's | which you keep credentials. See credential.h for details. | ||||||
| link:technical/api-credentials.html[credentials API] for details. |  | ||||||
|  |  | ||||||
| GIT | 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` | * `struct ll_merge_options` | ||||||
|  |  | ||||||
| This describes the set of options the calling program wants to affect | Check ll-merge.h for details. | ||||||
| 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. |  | ||||||
|  |  | ||||||
| Low-level (single file) merge | Low-level (single file) merge | ||||||
| ----------------------------- | ----------------------------- | ||||||
|  |  | ||||||
| `ll_merge`:: | Check ll-merge.h for details. | ||||||
|  |  | ||||||
| 	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) |  | ||||||
|  |  | ||||||
|  | @ -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 | === Basic Command Messages | ||||||
|  |  | ||||||
| These are concerned with the lifetime of the overall git process. | These are concerned with the lifetime of the overall git process. | ||||||
|  | e.g: `void trace2_initialize_clock()`, `void trace2_initialize()`, | ||||||
| `void trace2_initialize_clock()`:: | `int trace2_is_enabled()`, `void trace2_cmd_start(int argc, const char **argv)`. | ||||||
|  |  | ||||||
| 	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. |  | ||||||
|  |  | ||||||
| === Command Detail Messages | === Command Detail Messages | ||||||
|  |  | ||||||
| These are concerned with describing the specific Git command | These are concerned with describing the specific Git command | ||||||
| after the command line, config, and environment are inspected. | after the command line, config, and environment are inspected. | ||||||
|  | e.g: `void trace2_cmd_name(const char *name)`, | ||||||
| `void trace2_cmd_name(const char *name)`:: | `void trace2_cmd_mode(const char *mode)`. | ||||||
|  |  | ||||||
| 	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. |  | ||||||
|  |  | ||||||
| === Child Process Messages | === Child Process Messages | ||||||
|  |  | ||||||
| These are concerned with the various spawned child processes, | These are concerned with the various spawned child processes, | ||||||
| including shell scripts, git commands, editors, pagers, and hooks. | including shell scripts, git commands, editors, pagers, and hooks. | ||||||
|  |  | ||||||
| `void trace2_child_start(struct child_process *cmd)`:: | e.g: `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. |  | ||||||
|  |  | ||||||
| === Git Thread Messages | === Git Thread Messages | ||||||
|  |  | ||||||
| These messages are concerned with Git thread usage. | These messages are concerned with Git thread usage. | ||||||
|  |  | ||||||
| `void trace2_thread_start(const char *thread_name)`:: | e.g: `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()`. |  | ||||||
|  |  | ||||||
| === Region and Data Messages | === Region and Data Messages | ||||||
|  |  | ||||||
| These are concerned with recording performance data | 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)`:: | Refer to trace2.h for details about all trace2 functions. | ||||||
|  |  | ||||||
| `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. |  | ||||||
|  |  | ||||||
| == Trace2 Target Formats | == 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 | #ifndef ARGV_ARRAY_H | ||||||
| #define 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[]; | 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 { | struct argv_array { | ||||||
| 	const char **argv; | 	const char **argv; | ||||||
| 	int argc; | 	int argc; | ||||||
|  | @ -11,17 +35,55 @@ struct argv_array { | ||||||
|  |  | ||||||
| #define ARGV_ARRAY_INIT { empty_argv, 0, 0 } | #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 *); | 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 *); | 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))) | __attribute__((format (printf,2,3))) | ||||||
| const char *argv_array_pushf(struct argv_array *, const char *fmt, ...); | 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 | LAST_ARG_MUST_BE_NULL | ||||||
| void argv_array_pushl(struct argv_array *, ...); | 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 **); | 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 *); | void argv_array_pop(struct argv_array *); | ||||||
|  |  | ||||||
| /* Splits by whitespace; does not handle quoted arguments! */ | /* Splits by whitespace; does not handle quoted arguments! */ | ||||||
| void argv_array_split(struct argv_array *, const char *); | 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 *); | 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 *); | const char **argv_array_detach(struct argv_array *); | ||||||
|  |  | ||||||
| #endif /* ARGV_ARRAY_H */ | #endif /* ARGV_ARRAY_H */ | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								attr.c
								
								
								
								
							
							
						
						
									
										3
									
								
								attr.c
								
								
								
								
							|  | @ -1,7 +1,6 @@ | ||||||
| /* | /* | ||||||
|  * Handle git attributes.  See gitattributes(5) for a description of |  * Handle git attributes.  See gitattributes(5) for a description of | ||||||
|  * the file syntax, and Documentation/technical/api-gitattributes.txt |  * the file syntax, and attr.h for a description of the API. | ||||||
|  * for a description of the API. |  | ||||||
|  * |  * | ||||||
|  * One basic design decision here is that we are not going to support |  * One basic design decision here is that we are not going to support | ||||||
|  * an insanely large number of attributes. |  * an insanely large number of attributes. | ||||||
|  |  | ||||||
							
								
								
									
										141
									
								
								attr.h
								
								
								
								
							
							
						
						
									
										141
									
								
								attr.h
								
								
								
								
							|  | @ -1,9 +1,121 @@ | ||||||
| #ifndef ATTR_H | #ifndef ATTR_H | ||||||
| #define 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; | 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; | struct git_attr; | ||||||
|  |  | ||||||
| /* opaque structures used internally for attribute collection */ | /* 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__true[]; | ||||||
| extern const char git_attr__false[]; | 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) | #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) | #define ATTR_FALSE(v) ((v) == git_attr__false) | ||||||
|  |  | ||||||
|  | /* Returns true if the attribute is Unspecified for the path. */ | ||||||
| #define ATTR_UNSET(v) ((v) == NULL) | #define ATTR_UNSET(v) ((v) == NULL) | ||||||
|  |  | ||||||
| /* | /* This structure represents one attribute and its value. */ | ||||||
|  * 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. |  | ||||||
|  */ |  | ||||||
| struct attr_check_item { | struct attr_check_item { | ||||||
| 	const struct git_attr *attr; | 	const struct git_attr *attr; | ||||||
| 	const char *value; | 	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 { | struct attr_check { | ||||||
| 	int nr; | 	int nr; | ||||||
| 	int alloc; | 	int alloc; | ||||||
|  |  | ||||||
							
								
								
									
										41
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										41
									
								
								cache.h
								
								
								
								
							|  | @ -632,10 +632,43 @@ int daemonize(void); | ||||||
|  |  | ||||||
| #define alloc_nr(x) (((x)+16)*3/2) | #define alloc_nr(x) (((x)+16)*3/2) | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Realloc the buffer pointed at by variable 'x' so that it can hold |  * Dynamically growing an array using realloc() is error prone and boring. | ||||||
|  * at least 'nr' entries; the number of entries currently allocated |  * | ||||||
|  * is 'alloc', using the standard growing factor alloc_nr() macro. |  * 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 |  * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some | ||||||
|  * added niceties. |  * added niceties. | ||||||
|  |  | ||||||
							
								
								
									
										236
									
								
								credential.h
								
								
								
								
							
							
						
						
									
										236
									
								
								credential.h
								
								
								
								
							|  | @ -3,8 +3,208 @@ | ||||||
|  |  | ||||||
| #include "string-list.h" | #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 { | 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; | 	struct string_list helpers; | ||||||
|  |  | ||||||
| 	unsigned approved:1, | 	unsigned approved:1, | ||||||
| 		 configured:1, | 		 configured:1, | ||||||
| 		 quit:1, | 		 quit:1, | ||||||
|  | @ -19,16 +219,52 @@ struct credential { | ||||||
|  |  | ||||||
| #define CREDENTIAL_INIT { STRING_LIST_INIT_DUP } | #define CREDENTIAL_INIT { STRING_LIST_INIT_DUP } | ||||||
|  |  | ||||||
|  | /* Initialize a credential structure, setting all fields to empty. */ | ||||||
| void credential_init(struct credential *); | 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 *); | 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 *); | 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 *); | 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 *); | void credential_reject(struct credential *); | ||||||
|  |  | ||||||
| int credential_read(struct credential *, FILE *); | int credential_read(struct credential *, FILE *); | ||||||
| void credential_write(const 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); | void credential_from_url(struct credential *, const char *url); | ||||||
|  |  | ||||||
| int credential_match(const struct credential *have, | int credential_match(const struct credential *have, | ||||||
| 		     const struct credential *want); | 		     const struct credential *want); | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										126
									
								
								diff.h
								
								
								
								
							
							
						
						
									
										126
									
								
								diff.h
								
								
								
								
							|  | @ -9,6 +9,49 @@ | ||||||
| #include "object.h" | #include "object.h" | ||||||
| #include "oidset.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 combine_diff_path; | ||||||
| struct commit; | struct commit; | ||||||
| struct diff_filespec; | 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 } | #define DIFF_FLAGS_INIT { 0 } | ||||||
| struct diff_flags { | 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 recursive; | ||||||
| 	unsigned tree_in_recursive; | 	unsigned tree_in_recursive; | ||||||
|  |  | ||||||
|  | 	/* Affects the way how a file that is seemingly binary is treated. */ | ||||||
| 	unsigned binary; | 	unsigned binary; | ||||||
| 	unsigned text; | 	unsigned text; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Tells the patch output format not to use abbreviated object names on the | ||||||
|  | 	 * "index" lines. | ||||||
|  | 	 */ | ||||||
| 	unsigned full_index; | 	unsigned full_index; | ||||||
|  |  | ||||||
|  | 	/* Affects if diff-files shows removed files. */ | ||||||
| 	unsigned silent_on_remove; | 	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 find_copies_harder; | ||||||
|  |  | ||||||
| 	unsigned follow_renames; | 	unsigned follow_renames; | ||||||
| 	unsigned rename_empty; | 	unsigned rename_empty; | ||||||
|  |  | ||||||
|  | 	/* Internal; used for optimization to see if there is any change. */ | ||||||
| 	unsigned has_changes; | 	unsigned has_changes; | ||||||
|  |  | ||||||
| 	unsigned quick; | 	unsigned quick; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Tells diff-files that the input is not tracked files but files in random | ||||||
|  | 	 * locations on the filesystem. | ||||||
|  | 	 */ | ||||||
| 	unsigned no_index; | 	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; | 	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; | 	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 reverse_diff; | ||||||
|  |  | ||||||
| 	unsigned check_failed; | 	unsigned check_failed; | ||||||
| 	unsigned relative_name; | 	unsigned relative_name; | ||||||
| 	unsigned ignore_submodules; | 	unsigned ignore_submodules; | ||||||
|  | @ -131,36 +219,72 @@ enum diff_submodule_format { | ||||||
| 	DIFF_SUBMODULE_INLINE_DIFF | 	DIFF_SUBMODULE_INLINE_DIFF | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * the set of options the calling program wants to affect the operation of | ||||||
|  |  * diffcore library with. | ||||||
|  |  */ | ||||||
| struct diff_options { | struct diff_options { | ||||||
| 	const char *orderfile; | 	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 *pickaxe; | ||||||
|  |  | ||||||
| 	const char *single_follow; | 	const char *single_follow; | ||||||
| 	const char *a_prefix, *b_prefix; | 	const char *a_prefix, *b_prefix; | ||||||
| 	const char *line_prefix; | 	const char *line_prefix; | ||||||
| 	size_t line_prefix_length; | 	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; | 	struct diff_flags flags; | ||||||
|  |  | ||||||
| 	/* diff-filter bits */ | 	/* diff-filter bits */ | ||||||
| 	unsigned int filter; | 	unsigned int filter; | ||||||
|  |  | ||||||
| 	int use_color; | 	int use_color; | ||||||
|  |  | ||||||
|  | 	/* Number of context lines to generate in patch output. */ | ||||||
| 	int context; | 	int context; | ||||||
|  |  | ||||||
| 	int interhunkcontext; | 	int interhunkcontext; | ||||||
|  |  | ||||||
|  | 	/* Affects the way detection logic for complete rewrites, renames and | ||||||
|  | 	 * copies. | ||||||
|  | 	 */ | ||||||
| 	int break_opt; | 	int break_opt; | ||||||
| 	int detect_rename; | 	int detect_rename; | ||||||
|  |  | ||||||
| 	int irreversible_delete; | 	int irreversible_delete; | ||||||
| 	int skip_stat_unmatch; | 	int skip_stat_unmatch; | ||||||
| 	int line_termination; | 	int line_termination; | ||||||
|  |  | ||||||
|  | 	/* The output format used when `diff_flush()` is run. */ | ||||||
| 	int output_format; | 	int output_format; | ||||||
|  |  | ||||||
| 	unsigned pickaxe_opts; | 	unsigned pickaxe_opts; | ||||||
|  |  | ||||||
|  | 	/* Affects the way detection logic for complete rewrites, renames and | ||||||
|  | 	 * copies. | ||||||
|  | 	 */ | ||||||
| 	int rename_score; | 	int rename_score; | ||||||
| 	int rename_limit; | 	int rename_limit; | ||||||
|  |  | ||||||
| 	int needed_rename_limit; | 	int needed_rename_limit; | ||||||
| 	int degraded_cc_to_c; | 	int degraded_cc_to_c; | ||||||
| 	int show_rename_progress; | 	int show_rename_progress; | ||||||
| 	int dirstat_permille; | 	int dirstat_permille; | ||||||
| 	int setup; | 	int setup; | ||||||
|  |  | ||||||
|  | 	/* Number of hexdigits to abbreviate raw format output to. */ | ||||||
| 	int abbrev; | 	int abbrev; | ||||||
|  |  | ||||||
| 	int ita_invisible_in_index; | 	int ita_invisible_in_index; | ||||||
| /* white-space error highlighting */ | /* white-space error highlighting */ | ||||||
| #define WSEH_NEW (1<<12) | #define WSEH_NEW (1<<12) | ||||||
|  | @ -192,6 +316,7 @@ struct diff_options { | ||||||
| 	/* to support internal diff recursion by --follow hack*/ | 	/* to support internal diff recursion by --follow hack*/ | ||||||
| 	int found_follow; | 	int found_follow; | ||||||
|  |  | ||||||
|  | 	/* Callback which allows tweaking the options in diff_setup_done(). */ | ||||||
| 	void (*set_default)(struct diff_options *); | 	void (*set_default)(struct diff_options *); | ||||||
|  |  | ||||||
| 	FILE *file; | 	FILE *file; | ||||||
|  | @ -286,6 +411,7 @@ enum color_diff { | ||||||
| 	DIFF_FILE_OLD_BOLD = 21, | 	DIFF_FILE_OLD_BOLD = 21, | ||||||
| 	DIFF_FILE_NEW_BOLD = 22, | 	DIFF_FILE_NEW_BOLD = 22, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const char *diff_get_color(int diff_use_color, enum color_diff ix); | const char *diff_get_color(int diff_use_color, enum color_diff ix); | ||||||
| #define diff_get_color_opt(o, ix) \ | #define diff_get_color_opt(o, ix) \ | ||||||
| 	diff_get_color((o)->use_color, 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 */ | #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 diff_filespec { | ||||||
| 	struct object_id oid; | 	struct object_id oid; | ||||||
| 	char *path; | 	char *path; | ||||||
|  | @ -66,6 +72,17 @@ void diff_free_filespec_data(struct diff_filespec *); | ||||||
| void diff_free_filespec_blob(struct diff_filespec *); | void diff_free_filespec_blob(struct diff_filespec *); | ||||||
| int diff_filespec_is_binary(struct repository *, 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_filepair { | ||||||
| 	struct diff_filespec *one; | 	struct diff_filespec *one; | ||||||
| 	struct diff_filespec *two; | 	struct diff_filespec *two; | ||||||
|  | @ -77,6 +94,7 @@ struct diff_filepair { | ||||||
| 	unsigned done_skip_stat_unmatch : 1; | 	unsigned done_skip_stat_unmatch : 1; | ||||||
| 	unsigned skip_stat_unmatch_result : 1; | 	unsigned skip_stat_unmatch_result : 1; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged) | #define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged) | ||||||
|  |  | ||||||
| #define DIFF_PAIR_RENAME(p) ((p)->renamed_pair) | #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 *); | 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_queue_struct { | ||||||
| 	struct diff_filepair **queue; | 	struct diff_filepair **queue; | ||||||
| 	int alloc; | 	int alloc; | ||||||
| 	int nr; | 	int nr; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define DIFF_QUEUE_CLEAR(q) \ | #define DIFF_QUEUE_CLEAR(q) \ | ||||||
| 	do { \ | 	do { \ | ||||||
| 		(q)->queue = NULL; \ | 		(q)->queue = NULL; \ | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								dir.c
								
								
								
								
							
							
						
						
									
										2
									
								
								dir.c
								
								
								
								
							|  | @ -2,8 +2,6 @@ | ||||||
|  * This handles recursive filename detection with exclude |  * This handles recursive filename detection with exclude | ||||||
|  * files, index knowledge etc.. |  * files, index knowledge etc.. | ||||||
|  * |  * | ||||||
|  * See Documentation/technical/api-directory-listing.txt |  | ||||||
|  * |  | ||||||
|  * Copyright (C) Linus Torvalds, 2005-2006 |  * Copyright (C) Linus Torvalds, 2005-2006 | ||||||
|  *		 Junio Hamano, 2005-2006 |  *		 Junio Hamano, 2005-2006 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
							
								
								
									
										119
									
								
								dir.h
								
								
								
								
							
							
						
						
									
										119
									
								
								dir.h
								
								
								
								
							|  | @ -1,11 +1,44 @@ | ||||||
| #ifndef DIR_H | #ifndef DIR_H | ||||||
| #define DIR_H | #define DIR_H | ||||||
|  |  | ||||||
| /* See Documentation/technical/api-directory-listing.txt */ |  | ||||||
|  |  | ||||||
| #include "cache.h" | #include "cache.h" | ||||||
| #include "strbuf.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 { | struct dir_entry { | ||||||
| 	unsigned int len; | 	unsigned int len; | ||||||
| 	char name[FLEX_ARRAY]; /* more */ | 	char name[FLEX_ARRAY]; /* more */ | ||||||
|  | @ -144,25 +177,101 @@ struct untracked_cache { | ||||||
| 	unsigned int use_fsmonitor : 1; | 	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 { | 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 { | 	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, | 		DIR_SHOW_IGNORED = 1<<0, | ||||||
|  |  | ||||||
|  | 		/* Include a directory that is not tracked. */ | ||||||
| 		DIR_SHOW_OTHER_DIRECTORIES = 1<<1, | 		DIR_SHOW_OTHER_DIRECTORIES = 1<<1, | ||||||
|  |  | ||||||
|  | 		/* Do not include a directory that is not tracked and is empty. */ | ||||||
| 		DIR_HIDE_EMPTY_DIRECTORIES = 1<<2, | 		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, | 		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, | 		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_SHOW_IGNORED_TOO = 1<<5, | ||||||
|  |  | ||||||
| 		DIR_COLLECT_KILLED_ONLY = 1<<6, | 		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, | 		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_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8, | ||||||
|  |  | ||||||
| 		DIR_SKIP_NESTED_GIT = 1<<9 | 		DIR_SKIP_NESTED_GIT = 1<<9 | ||||||
| 	} flags; | 	} flags; | ||||||
|  |  | ||||||
|  | 	/* An array of `struct dir_entry`, each element of which describes a path. */ | ||||||
| 	struct dir_entry **entries; | 	struct dir_entry **entries; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * used for ignored paths with the `DIR_SHOW_IGNORED_TOO` and | ||||||
|  | 	 * `DIR_COLLECT_IGNORED` flags. | ||||||
|  | 	 */ | ||||||
| 	struct dir_entry **ignored; | 	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; | 	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 |  * 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 |  * file specified by the graph diff options. This is necessary so that | ||||||
|  * graph_show_strbuf can be called even with a NULL graph. |  * 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, | static void graph_show_strbuf(struct git_graph *graph, | ||||||
| 			      FILE *file, | 			      FILE *file, | ||||||
|  |  | ||||||
							
								
								
									
										121
									
								
								graph.h
								
								
								
								
							
							
						
						
									
										121
									
								
								graph.h
								
								
								
								
							|  | @ -2,6 +2,103 @@ | ||||||
| #define GRAPH_H | #define GRAPH_H | ||||||
| #include "diff.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 */ | /* A graph is a pointer to this opaque structure */ | ||||||
| struct git_graph; | 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, |  * If graph_update() is called before graph_is_commit_finished() returns 1, | ||||||
|  * the next call to graph_next_line() will output an ellipsis ("...") |  * the next call to graph_next_line() will output an ellipsis ("...") | ||||||
|  * to indicate that a portion of the graph is missing. |  * 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); | 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 |  * for this commit.  If 0 is returned, graph_next_line() may still be | ||||||
|  * called without calling graph_update(), and it will merely output |  * called without calling graph_update(), and it will merely output | ||||||
|  * appropriate "vertical padding" in the graph. |  * 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); | 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 |  * 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. |  * 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); | 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 |  * This is similar to graph_show_strbuf(), but it always prints the | ||||||
|  * remainder of the graph. |  * 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 |  * If the strbuf ends with a newline, the output printed by | ||||||
|  * graph_show_commit_msg() will end with a newline.  If the strbuf is |  * graph_show_commit_msg() will end with a newline.  If the strbuf is | ||||||
|  * missing a terminating newline (including if it is empty), the output |  * 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" | #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; | 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 { | 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 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; | 	unsigned renormalize : 1; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Increase the length of conflict markers so that nested conflicts | ||||||
|  | 	 * can be differentiated. | ||||||
|  | 	 */ | ||||||
| 	unsigned extra_marker_size; | 	unsigned extra_marker_size; | ||||||
|  |  | ||||||
|  | 	/* Extra xpparam_t flags as defined in xdiff/xdiff.h. */ | ||||||
| 	long xdl_opts; | 	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, | int ll_merge(mmbuffer_t *result_buf, | ||||||
| 	     const char *path, | 	     const char *path, | ||||||
| 	     mmfile_t *ancestor, const char *ancestor_label, | 	     mmfile_t *ancestor, const char *ancestor_label, | ||||||
|  |  | ||||||
|  | @ -1,6 +1,10 @@ | ||||||
| #ifndef PARSE_OPTIONS_H | #ifndef PARSE_OPTIONS_H | ||||||
| #define PARSE_OPTIONS_H | #define PARSE_OPTIONS_H | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Refer to Documentation/technical/api-parse-options.txt for the API doc. | ||||||
|  |  */ | ||||||
|  |  | ||||||
| enum parse_opt_type { | enum parse_opt_type { | ||||||
| 	/* special types */ | 	/* special types */ | ||||||
| 	OPTION_END, | 	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 */ | #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 { | struct pathspec { | ||||||
| 	int nr; | 	int nr; | ||||||
| 	unsigned int has_wildcard:1; | 	unsigned int has_wildcard:1; | ||||||
|  | @ -73,12 +78,39 @@ struct pathspec { | ||||||
|  */ |  */ | ||||||
| #define PATHSPEC_LITERAL_PATH (1<<6) | #define PATHSPEC_LITERAL_PATH (1<<6) | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Given command line arguments and a prefix, convert the input to |  * Given command line arguments and a prefix, convert the input to | ||||||
|  * pathspec. die() if any magic in magic_mask is used. |  * pathspec. die() if any magic in magic_mask is used. | ||||||
|  * |  * | ||||||
|  * Any arguments used are copied. It is safe for the caller to modify |  * Any arguments used are copied. It is safe for the caller to modify | ||||||
|  * or free 'prefix' and 'args' after calling this function. |  * 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, | void parse_pathspec(struct pathspec *pathspec, | ||||||
| 		    unsigned magic_mask, | 		    unsigned magic_mask, | ||||||
|  | @ -95,6 +127,7 @@ void parse_pathspec_file(struct pathspec *pathspec, | ||||||
| 			 const char *prefix, | 			 const char *prefix, | ||||||
| 			 const char *file, | 			 const char *file, | ||||||
| 			 int nul_term_line); | 			 int nul_term_line); | ||||||
|  |  | ||||||
| void copy_pathspec(struct pathspec *dst, const struct pathspec *src); | void copy_pathspec(struct pathspec *dst, const struct pathspec *src); | ||||||
| void clear_pathspec(struct pathspec *); | 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, | int refs_for_each_remote_ref(struct ref_store *refs, | ||||||
| 			     each_ref_fn fn, void *cb_data); | 			     each_ref_fn fn, void *cb_data); | ||||||
|  |  | ||||||
|  | /* just iterates the head ref. */ | ||||||
| int head_ref(each_ref_fn fn, void *cb_data); | int head_ref(each_ref_fn fn, void *cb_data); | ||||||
|  |  | ||||||
|  | /* iterates all refs. */ | ||||||
| int for_each_ref(each_ref_fn fn, void *cb_data); | 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 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, | int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix, | ||||||
| 			     each_ref_fn fn, void *cb_data, | 			     each_ref_fn fn, void *cb_data, | ||||||
| 			     unsigned int broken); | 			     unsigned int broken); | ||||||
| int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, | int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, | ||||||
| 			unsigned int broken); | 			unsigned int broken); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * iterate refs from the respective area. | ||||||
|  |  */ | ||||||
| int for_each_tag_ref(each_ref_fn fn, void *cb_data); | 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_branch_ref(each_ref_fn fn, void *cb_data); | ||||||
| int for_each_remote_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); | 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(each_ref_fn fn, const char *pattern, void *cb_data); | ||||||
|  |  | ||||||
| int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, | int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, | ||||||
| 			 const char *prefix, void *cb_data); | 			 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); | int ref_storage_backend_exists(const char *name); | ||||||
|  |  | ||||||
| struct ref_store *get_main_ref_store(struct repository *r); | 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 |  * Return the ref_store instance for the specified submodule. For the | ||||||
|  * main repository, use submodule==NULL; such a call cannot fail. For |  * 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_FETCH { .fetch = REFSPEC_FETCH } | ||||||
| #define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH } | #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 { | ||||||
| 	struct refspec_item *items; | 	struct refspec_item *items; | ||||||
| 	int alloc; | 	int alloc; | ||||||
|  |  | ||||||
							
								
								
									
										57
									
								
								remote.h
								
								
								
								
							
							
						
						
									
										57
									
								
								remote.h
								
								
								
								
							|  | @ -6,6 +6,14 @@ | ||||||
| #include "hashmap.h" | #include "hashmap.h" | ||||||
| #include "refspec.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 { | enum { | ||||||
| 	REMOTE_UNCONFIGURED = 0, | 	REMOTE_UNCONFIGURED = 0, | ||||||
| 	REMOTE_CONFIG, | 	REMOTE_CONFIG, | ||||||
|  | @ -16,16 +24,22 @@ enum { | ||||||
| struct remote { | struct remote { | ||||||
| 	struct hashmap_entry ent; | 	struct hashmap_entry ent; | ||||||
|  |  | ||||||
|  | 	/* The user's nickname for the remote */ | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  |  | ||||||
| 	int origin, configured_in_repo; | 	int origin, configured_in_repo; | ||||||
|  |  | ||||||
| 	const char *foreign_vcs; | 	const char *foreign_vcs; | ||||||
|  |  | ||||||
|  | 	/* An array of all of the url_nr URLs configured for the remote */ | ||||||
| 	const char **url; | 	const char **url; | ||||||
|  |  | ||||||
| 	int url_nr; | 	int url_nr; | ||||||
| 	int url_alloc; | 	int url_alloc; | ||||||
|  |  | ||||||
|  | 	/* An array of all of the pushurl_nr push URLs configured for the remote */ | ||||||
| 	const char **pushurl; | 	const char **pushurl; | ||||||
|  |  | ||||||
| 	int pushurl_nr; | 	int pushurl_nr; | ||||||
| 	int pushurl_alloc; | 	int pushurl_alloc; | ||||||
|  |  | ||||||
|  | @ -34,32 +48,47 @@ struct remote { | ||||||
| 	struct refspec fetch; | 	struct refspec fetch; | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
|  | 	 * The setting for whether to fetch tags (as a separate rule from the | ||||||
|  | 	 * configured refspecs); | ||||||
| 	 * -1 to never fetch tags | 	 * -1 to never fetch tags | ||||||
| 	 * 0 to auto-follow tags on heuristic (default) | 	 * 0 to auto-follow tags on heuristic (default) | ||||||
| 	 * 1 to always auto-follow tags | 	 * 1 to always auto-follow tags | ||||||
| 	 * 2 to always fetch tags | 	 * 2 to always fetch tags | ||||||
| 	 */ | 	 */ | ||||||
| 	int fetch_tags; | 	int fetch_tags; | ||||||
|  |  | ||||||
| 	int skip_default_update; | 	int skip_default_update; | ||||||
| 	int mirror; | 	int mirror; | ||||||
| 	int prune; | 	int prune; | ||||||
| 	int prune_tags; | 	int prune_tags; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The configured helper programs to run on the remote side, for | ||||||
|  | 	 * Git-native protocols. | ||||||
|  | 	 */ | ||||||
| 	const char *receivepack; | 	const char *receivepack; | ||||||
| 	const char *uploadpack; | 	const char *uploadpack; | ||||||
|  |  | ||||||
| 	/* | 	/* The proxy to use for curl (http, https, ftp, etc.) URLs. */ | ||||||
| 	 * for curl remotes only |  | ||||||
| 	 */ |  | ||||||
| 	char *http_proxy; | 	char *http_proxy; | ||||||
|  |  | ||||||
|  | 	/* The method used for authenticating against `http_proxy`. */ | ||||||
| 	char *http_proxy_authmethod; | 	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 *remote_get(const char *name); | ||||||
|  |  | ||||||
| struct remote *pushremote_get(const char *name); | struct remote *pushremote_get(const char *name); | ||||||
| int remote_is_configured(struct remote *remote, int in_repo); | int remote_is_configured(struct remote *remote, int in_repo); | ||||||
|  |  | ||||||
| typedef int each_remote_fn(struct remote *remote, void *priv); | 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 for_each_remote(each_remote_fn fn, void *priv); | ||||||
|  |  | ||||||
| int remote_has_url(struct remote *remote, const char *url); | 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); | 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 { | struct branch { | ||||||
|  |  | ||||||
|  | 	/* The short name of the branch. */ | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  |  | ||||||
|  | 	/* The full path for the branch ref. */ | ||||||
| 	const char *refname; | 	const char *refname; | ||||||
|  |  | ||||||
|  | 	/* The name of the remote listed in the configuration. */ | ||||||
| 	const char *remote_name; | 	const char *remote_name; | ||||||
|  |  | ||||||
| 	const char *pushremote_name; | 	const char *pushremote_name; | ||||||
|  |  | ||||||
|  | 	/* An array of the "merge" lines in the configuration. */ | ||||||
| 	const char **merge_name; | 	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; | 	struct refspec_item **merge; | ||||||
|  |  | ||||||
|  | 	/* The number of merge configurations */ | ||||||
| 	int merge_nr; | 	int merge_nr; | ||||||
|  |  | ||||||
| 	int merge_alloc; | 	int merge_alloc; | ||||||
|  |  | ||||||
| 	const char *push_tracking_ref; | 	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, | const char *remote_ref_for_branch(struct branch *branch, int for_push, | ||||||
| 				  int *explicit); | 				  int *explicit); | ||||||
|  |  | ||||||
|  | /* returns true if the given branch has merge configuration given. */ | ||||||
| int branch_has_merge_config(struct branch *branch); | int branch_has_merge_config(struct branch *branch); | ||||||
|  |  | ||||||
| int branch_merge_matches(struct branch *, int n, const char *); | int branch_merge_matches(struct branch *, int n, const char *); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  |  | ||||||
							
								
								
									
										59
									
								
								revision.h
								
								
								
								
							
							
						
						
									
										59
									
								
								revision.h
								
								
								
								
							|  | @ -9,6 +9,19 @@ | ||||||
| #include "diff.h" | #include "diff.h" | ||||||
| #include "commit-slab-decl.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 */ | /* Remember to update object flag allocation in object.h */ | ||||||
| #define SEEN		(1u<<0) | #define SEEN		(1u<<0) | ||||||
| #define UNINTERESTING   (1u<<1) | #define UNINTERESTING   (1u<<1) | ||||||
|  | @ -306,11 +319,29 @@ struct setup_revision_opt { | ||||||
| #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS | #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS | ||||||
| #define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix) | #define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix) | ||||||
| #endif | #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, | void repo_init_revisions(struct repository *r, | ||||||
| 			 struct rev_info *revs, | 			 struct rev_info *revs, | ||||||
| 			 const char *prefix); | 			 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, | int setup_revisions(int argc, const char **argv, struct rev_info *revs, | ||||||
| 		    struct setup_revision_opt *); | 		    struct setup_revision_opt *); | ||||||
|  |  | ||||||
| void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx, | void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx, | ||||||
| 			const struct option *options, | 			const struct option *options, | ||||||
| 			const char * const usagestr[]); | 			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 handle_revision_arg(const char *arg, struct rev_info *revs, | ||||||
| 			int flags, unsigned revarg_opt); | 			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); | 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); | 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); | struct commit *get_revision(struct rev_info *revs); | ||||||
|  |  | ||||||
| const char *get_revision_mark(const struct rev_info *revs, | const char *get_revision_mark(const struct rev_info *revs, | ||||||
| 			      const struct commit *commit); | 			      const struct commit *commit); | ||||||
| void put_revision_mark(const struct rev_info *revs, | 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 *); | 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, | void add_pending_object(struct rev_info *revs, | ||||||
| 			struct object *obj, const char *name); | 			struct object *obj, const char *name); | ||||||
|  |  | ||||||
| void add_pending_oid(struct rev_info *revs, | void add_pending_oid(struct rev_info *revs, | ||||||
| 		     const char *name, const struct object_id *oid, | 		     const char *name, const struct object_id *oid, | ||||||
| 		     unsigned int flags); | 		     unsigned int flags); | ||||||
|  |  | ||||||
							
								
								
									
										252
									
								
								run-command.h
								
								
								
								
							
							
						
						
									
										252
									
								
								run-command.h
								
								
								
								
							|  | @ -5,8 +5,60 @@ | ||||||
|  |  | ||||||
| #include "argv-array.h" | #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 { | 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; | 	const char **argv; | ||||||
|  |  | ||||||
| 	struct argv_array args; | 	struct argv_array args; | ||||||
| 	struct argv_array env_array; | 	struct argv_array env_array; | ||||||
| 	pid_t pid; | 	pid_t pid; | ||||||
|  | @ -18,8 +70,8 @@ struct child_process { | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Using .in, .out, .err: | 	 * Using .in, .out, .err: | ||||||
| 	 * - Specify 0 for no redirections (child inherits stdin, stdout, | 	 * - Specify 0 for no redirections. No new file descriptor is allocated. | ||||||
| 	 *   stderr from parent). | 	 * (child inherits stdin, stdout, stderr from parent). | ||||||
| 	 * - Specify -1 to have a pipe allocated as follows: | 	 * - Specify -1 to have a pipe allocated as follows: | ||||||
| 	 *     .in: returns the writable pipe end; parent writes to it, | 	 *     .in: returns the writable pipe end; parent writes to it, | ||||||
| 	 *          the readable pipe end becomes child's stdin | 	 *          the readable pipe end becomes child's stdin | ||||||
|  | @ -37,13 +89,43 @@ struct child_process { | ||||||
| 	int in; | 	int in; | ||||||
| 	int out; | 	int out; | ||||||
| 	int err; | 	int err; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * To specify a new initial working directory for the sub-process, | ||||||
|  | 	 * specify it in the .dir member. | ||||||
|  | 	 */ | ||||||
| 	const char *dir; | 	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; | 	const char *const *env; | ||||||
|  |  | ||||||
| 	unsigned no_stdin:1; | 	unsigned no_stdin:1; | ||||||
| 	unsigned no_stdout:1; | 	unsigned no_stdout:1; | ||||||
| 	unsigned no_stderr: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 silent_exec_failure:1; | ||||||
|  |  | ||||||
| 	unsigned stdout_to_stderr:1; | 	unsigned stdout_to_stderr:1; | ||||||
| 	unsigned use_shell:1; | 	unsigned use_shell:1; | ||||||
| 	unsigned clean_on_exit:1; | 	unsigned clean_on_exit:1; | ||||||
|  | @ -53,13 +135,63 @@ struct child_process { | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT } | #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 *); | 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 *); | void child_process_clear(struct child_process *); | ||||||
|  |  | ||||||
| int is_executable(const char *name); | 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 *); | 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(struct child_process *); | ||||||
|  |  | ||||||
| int finish_command_in_signal(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 *); | 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_*. |  * overwritten by further calls to find_hook and run_hook_*. | ||||||
|  */ |  */ | ||||||
| const char *find_hook(const char *name); | 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 | LAST_ARG_MUST_BE_NULL | ||||||
| int run_hook_le(const char *const *env, const char *name, ...); | 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); | 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_SILENT_EXEC_FAILURE 8 | ||||||
| #define RUN_USING_SHELL 16 | #define RUN_USING_SHELL 16 | ||||||
| #define RUN_CLEAN_ON_EXIT 32 | #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(const char **argv, int opt); | ||||||
| int run_command_v_opt_tr2(const char **argv, int opt, const char *tr2_class); | 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 |  * It is expected that no synchronization and mutual exclusion between | ||||||
|  * the caller and the feed function is necessary so that the function |  * the caller and the feed function is necessary so that the function | ||||||
|  * can run in a thread without interfering with the caller. |  * 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 { | struct async { | ||||||
| 	/* |  | ||||||
| 	 * proc reads from in; closes it before return | 	/** | ||||||
| 	 * proc writes to out; closes it before return | 	 * The function pointer in .proc has the following signature: | ||||||
| 	 * returns 0 on success, non-zero on failure | 	 * | ||||||
|  | 	 *	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); | 	int (*proc)(int in, int out, void *data); | ||||||
|  |  | ||||||
| 	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 in;		/* caller writes here and closes it */ | ||||||
| 	int out;	/* caller reads from here and closes it */ | 	int out;	/* caller reads from here and closes it */ | ||||||
| #ifdef NO_PTHREADS | #ifdef NO_PTHREADS | ||||||
|  | @ -146,8 +373,19 @@ struct async { | ||||||
| 	int isolate_sigpipe; | 	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); | 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 finish_async(struct async *async); | ||||||
|  |  | ||||||
| int in_async(void); | int in_async(void); | ||||||
| int async_with_fork(void); | int async_with_fork(void); | ||||||
| void check_pipe(int err); | void check_pipe(int err); | ||||||
|  |  | ||||||
|  | @ -48,7 +48,7 @@ int oid_array_for_each(struct oid_array *array, | ||||||
| { | { | ||||||
| 	int i; | 	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++) { | 	for (i = 0; i < array->nr; i++) { | ||||||
| 		int ret = fn(array->oid + i, data); | 		int ret = fn(array->oid + i, data); | ||||||
|  |  | ||||||
							
								
								
									
										80
									
								
								sha1-array.h
								
								
								
								
							
							
						
						
									
										80
									
								
								sha1-array.h
								
								
								
								
							|  | @ -1,6 +1,52 @@ | ||||||
| #ifndef SHA1_ARRAY_H | #ifndef SHA1_ARRAY_H | ||||||
| #define 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 oid_array { | ||||||
| 	struct object_id *oid; | 	struct object_id *oid; | ||||||
| 	int nr; | 	int nr; | ||||||
|  | @ -10,18 +56,52 @@ struct oid_array { | ||||||
|  |  | ||||||
| #define OID_ARRAY_INIT { NULL, 0, 0, 0 } | #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); | 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); | 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); | void oid_array_clear(struct oid_array *array); | ||||||
|  |  | ||||||
| typedef int (*for_each_oid_fn)(const struct object_id *oid, | typedef int (*for_each_oid_fn)(const struct object_id *oid, | ||||||
| 			       void *data); | 			       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, | int oid_array_for_each(struct oid_array *array, | ||||||
| 		       for_each_oid_fn fn, | 		       for_each_oid_fn fn, | ||||||
| 		       void *data); | 		       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, | int oid_array_for_each_unique(struct oid_array *array, | ||||||
| 			      for_each_oid_fn fn, | 			      for_each_oid_fn fn, | ||||||
| 			      void *data); | 			      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, | void oid_array_filter(struct oid_array *array, | ||||||
| 		      for_each_oid_fn want, | 		      for_each_oid_fn want, | ||||||
| 		      void *cbdata); | 		      void *cbdata); | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								sigchain.h
								
								
								
								
							
							
						
						
									
										45
									
								
								sigchain.h
								
								
								
								
							|  | @ -1,12 +1,57 @@ | ||||||
| #ifndef SIGCHAIN_H | #ifndef SIGCHAIN_H | ||||||
| #define 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); | typedef void (*sigchain_fun)(int); | ||||||
|  |  | ||||||
|  | /* You can sigchain_push and sigchain_pop individual signals. */ | ||||||
| int sigchain_push(int sig, sigchain_fun f); | int sigchain_push(int sig, sigchain_fun f); | ||||||
| int sigchain_pop(int sig); | 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_push_common(sigchain_fun f); | ||||||
|  |  | ||||||
| void sigchain_pop_common(void); | void sigchain_pop_common(void); | ||||||
|  |  | ||||||
| #endif /* SIGCHAIN_H */ | #endif /* SIGCHAIN_H */ | ||||||
|  |  | ||||||
|  | @ -7,9 +7,31 @@ | ||||||
| #include "submodule.h" | #include "submodule.h" | ||||||
| #include "strbuf.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 |  * 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 { | struct submodule { | ||||||
| 	const char *path; | 	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); | int parse_push_recurse_submodules_arg(const char *opt, const char *arg); | ||||||
| void repo_read_gitmodules(struct repository *repo); | void repo_read_gitmodules(struct repository *repo); | ||||||
| void gitmodules_config_oid(const struct object_id *commit_oid); | 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 submodule *submodule_from_name(struct repository *r, | ||||||
| 					    const struct object_id *commit_or_tree, | 					    const struct object_id *commit_or_tree, | ||||||
| 					    const char *name); | 					    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 submodule *submodule_from_path(struct repository *r, | ||||||
| 					    const struct object_id *commit_or_tree, | 					    const struct object_id *commit_or_tree, | ||||||
| 					    const char *path); | 					    const char *path); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Use these to free the internally cached values. | ||||||
|  |  */ | ||||||
| void submodule_free(struct repository *r); | void submodule_free(struct repository *r); | ||||||
|  |  | ||||||
| int print_config_from_gitmodules(struct repository *repo, const char *key); | int print_config_from_gitmodules(struct repository *repo, const char *key); | ||||||
| int config_set_in_gitmodules_file_gently(const char *key, const char *value); | 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 "git-compat-util.h" | ||||||
| #include "strbuf.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 { | struct trace_key { | ||||||
| 	const char * const key; | 	const char * const key; | ||||||
| 	int fd; | 	int fd; | ||||||
|  | @ -18,31 +94,84 @@ extern struct trace_key trace_perf_key; | ||||||
| extern struct trace_key trace_setup_key; | extern struct trace_key trace_setup_key; | ||||||
|  |  | ||||||
| void trace_repo_setup(const char *prefix); | 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); | 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); | 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); | uint64_t getnanotime(void); | ||||||
|  |  | ||||||
| void trace_command_performance(const char **argv); | void trace_command_performance(const char **argv); | ||||||
| void trace_verbatim(struct trace_key *key, const void *buf, unsigned len); | void trace_verbatim(struct trace_key *key, const void *buf, unsigned len); | ||||||
| uint64_t trace_performance_enter(void); | uint64_t trace_performance_enter(void); | ||||||
|  |  | ||||||
| #ifndef HAVE_VARIADIC_MACROS | #ifndef HAVE_VARIADIC_MACROS | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Prints a formatted message, similar to printf. | ||||||
|  |  */ | ||||||
| __attribute__((format (printf, 1, 2))) | __attribute__((format (printf, 1, 2))) | ||||||
| void trace_printf(const char *format, ...); | void trace_printf(const char *format, ...); | ||||||
|  |  | ||||||
| __attribute__((format (printf, 2, 3))) | __attribute__((format (printf, 2, 3))) | ||||||
| void trace_printf_key(struct trace_key *key, const char *format, ...); | 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))) | __attribute__((format (printf, 2, 3))) | ||||||
| void trace_argv_printf(const char **argv, const char *format, ...); | 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); | 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))) | __attribute__((format (printf, 2, 3))) | ||||||
| void trace_performance(uint64_t nanos, const char *format, ...); | 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))) | __attribute__((format (printf, 2, 3))) | ||||||
| void trace_performance_since(uint64_t start, const char *format, ...); | void trace_performance_since(uint64_t start, const char *format, ...); | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										124
									
								
								trace2.h
								
								
								
								
							
							
						
						
									
										124
									
								
								trace2.h
								
								
								
								
							|  | @ -1,6 +1,40 @@ | ||||||
| #ifndef TRACE2_H | #ifndef TRACE2_H | ||||||
| #define 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 child_process; | ||||||
| struct repository; | struct repository; | ||||||
| struct json_writer; | struct json_writer; | ||||||
|  | @ -39,7 +73,12 @@ void trace2_initialize_clock(void); | ||||||
| /* | /* | ||||||
|  * Initialize TRACE2 tracing facility if any of the builtin TRACE2 |  * Initialize TRACE2 tracing facility if any of the builtin TRACE2 | ||||||
|  * targets are enabled in the system config or the environment. |  * 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 |  * Cleanup/Termination is handled automatically by a registered | ||||||
|  * atexit() routine. |  * atexit() routine. | ||||||
|  | @ -49,7 +88,7 @@ void trace2_initialize_fl(const char *file, int line); | ||||||
| #define trace2_initialize() trace2_initialize_fl(__FILE__, __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); | 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)) | #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, | void trace2_cmd_alias_fl(const char *file, int line, const char *alias, | ||||||
| 			 const char **argv); | 			 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)) | 	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. |  * settings. | ||||||
|  * |  * | ||||||
|  * Use the TR2_SYSENV_CFG_PARAM setting to register a comma-separated |  * 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 |  * 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 |  * Use this for new/updated config settings created/updated after | ||||||
|  * trace2_cmd_list_config() is called. |  * 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) \ | #define trace2_cmd_set_config(k, v) \ | ||||||
| 	trace2_cmd_set_config_fl(__FILE__, __LINE__, (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 |  * Before calling optionally set "cmd->trace2_child_class" to a string | ||||||
|  * describing the type of the child process.  For example, "editor" or |  * describing the type of the child process.  For example, "editor" or | ||||||
|  * "pager". |  * "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, | void trace2_child_start_fl(const char *file, int line, | ||||||
| 			   struct child_process *cmd); | 			   struct child_process *cmd); | ||||||
|  |  | ||||||
| #define trace2_child_start(cmd) trace2_child_start_fl(__FILE__, __LINE__, (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, | void trace2_child_exit_fl(const char *file, int line, struct child_process *cmd, | ||||||
| 			  int child_exit_code); | 			  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) \ | #define trace2_child_exit(cmd, code) \ | ||||||
| 	trace2_child_exit_fl(__FILE__, __LINE__, (cmd), (code)) | 	trace2_child_exit_fl(__FILE__, __LINE__, (cmd), (code)) | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Emit an 'exec' event prior to calling one of exec(), execv(), |  * Emit an 'exec' event prior to calling one of exec(), execv(), | ||||||
|  * execvp(), and etc.  On Unix-derived systems, this will be the |  * execvp(), and etc.  On Unix-derived systems, this will be the | ||||||
|  * last event emitted for the current process, unless the exec |  * last event emitted for the current process, unless the exec | ||||||
|  * fails.  On Windows, exec() behaves like 'child_start' and a |  * fails.  On Windows, exec() behaves like 'child_start' and a | ||||||
|  * waitpid(), so additional events may be emitted. |  * 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, | int trace2_exec_fl(const char *file, int line, const char *exe, | ||||||
| 		   const char **argv); | 		   const char **argv); | ||||||
|  |  | ||||||
| #define trace2_exec(exe, argv) trace2_exec_fl(__FILE__, __LINE__, (exe), (argv)) | #define trace2_exec(exe, argv) trace2_exec_fl(__FILE__, __LINE__, (exe), (argv)) | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Emit an 'exec_result' when possible.  On Unix-derived systems, |  * Emit an 'exec_result' when possible.  On Unix-derived systems, | ||||||
|  * this should be called after exec() returns (which only happens |  * this should be called after exec() returns (which only happens | ||||||
|  * when there is an error starting the new process).  On Windows, |  * 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__) | #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 |  * This message is intended to report some global aspect of the current | ||||||
|  * run such as an important configuration setting or command line |  * command, such as a configuration setting or command line switch that | ||||||
|  * option that significantly changes command behavior. |  * 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, | void trace2_def_param_fl(const char *file, int line, const char *param, | ||||||
| 			 const char *value); | 			 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. |  * a trace2-repo-id to be used in subsequent activity events. | ||||||
|  * |  * | ||||||
|  * Emits a 'worktree' event for this repo instance. |  * 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); | 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) | #define trace2_def_repo(repo) trace2_def_repo_fl(__FILE__, __LINE__, repo) | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Emit a 'region_enter' event for <category>.<label> with optional |  * Emit a 'region_enter' event for <category>.<label> with optional | ||||||
|  * repo-id and printf message. |  * repo-id and printf message. | ||||||
|  * |  * | ||||||
|  * Enter a new nesting level on the current thread and remember the |  * This function pushes a new region nesting stack level on the current | ||||||
|  * current time.  This controls the indenting of all subsequent events |  * thread and starts a clock for the new stack frame. | ||||||
|  * on this thread. |  * | ||||||
|  |  * 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, | void trace2_region_enter_fl(const char *file, int line, const char *category, | ||||||
| 			    const char *label, const struct repository *repo, ...); | 			    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 */ | /* clang-format on */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Emit a 'region_leave' event for <category>.<label> with optional |  * Emit a 'region_leave' event for <category>.<label> with optional | ||||||
|  * repo-id and printf message. |  * repo-id and printf message. | ||||||
|  * |  * | ||||||
|  * Leave current nesting level and report the elapsed time spent |  * Leave current nesting level and report the elapsed time spent | ||||||
|  * in this nesting level. |  * 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, | void trace2_region_leave_fl(const char *file, int line, const char *category, | ||||||
| 			    const char *label, const struct repository *repo, ...); | 			    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 */ | /* clang-format on */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /** | ||||||
|  * Emit a key-value pair 'data' event of the form <category>.<key> = <value>. |  * Emit a key-value pair 'data' event of the form <category>.<key> = <value>. | ||||||
|  * This event implicitly contains information about thread, nesting region, |  * This event implicitly contains information about thread, nesting region, | ||||||
|  * and optional repo-id. |  * 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 |  * On event-based TRACE2 targets, this generates a 'data' event suitable | ||||||
|  * for post-processing.  On printf-based TRACE2 targets, this is converted |  * 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" | #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 name_entry { | ||||||
| 	struct object_id oid; | 	struct object_id oid; | ||||||
| 	const char *path; | 	const char *path; | ||||||
|  | @ -10,12 +17,29 @@ struct name_entry { | ||||||
| 	unsigned int mode; | 	unsigned int mode; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A semi-opaque data structure used to maintain the current state of the walk. | ||||||
|  |  */ | ||||||
| struct tree_desc { | struct tree_desc { | ||||||
|  | 	/* | ||||||
|  | 	 * pointer into the memory representation of the tree. It always | ||||||
|  | 	 * points at the current entry being visited. | ||||||
|  | 	 */ | ||||||
| 	const void *buffer; | 	const void *buffer; | ||||||
|  |  | ||||||
|  | 	/* points to the current entry being visited. */ | ||||||
| 	struct name_entry entry; | 	struct name_entry entry; | ||||||
|  |  | ||||||
|  | 	/* counts the number of bytes left in the `buffer`. */ | ||||||
| 	unsigned int size; | 	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) | static inline const struct object_id *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned short *modep) | ||||||
| { | { | ||||||
| 	*pathp = desc->entry.path; | 	*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; | 	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) | static inline int tree_entry_len(const struct name_entry *ne) | ||||||
| { | { | ||||||
| 	return ne->pathlen; | 	return ne->pathlen; | ||||||
|  | @ -33,52 +62,141 @@ static inline int tree_entry_len(const struct name_entry *ne) | ||||||
|  * corrupt tree entry rather than dying, |  * 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 *); | void update_tree_entry(struct tree_desc *); | ||||||
|  |  | ||||||
| int update_tree_entry_gently(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); | 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); | 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() |  * Visit the next entry in a tree. Returns 1 when there are more entries | ||||||
|  * and returns true for success |  * 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(struct tree_desc *, struct name_entry *); | ||||||
|  |  | ||||||
| int tree_entry_gently(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, | void *fill_tree_descriptor(struct repository *r, | ||||||
| 			   struct tree_desc *desc, | 			   struct tree_desc *desc, | ||||||
| 			   const struct object_id *oid); | 			   const struct object_id *oid); | ||||||
|  |  | ||||||
| struct traverse_info; | struct traverse_info; | ||||||
| typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, 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); | 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); | 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 { | struct traverse_info { | ||||||
| 	const char *traverse_path; | 	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; | 	struct traverse_info *prev; | ||||||
|  |  | ||||||
|  | 	/* is the entry for the current tree (if the tree is a subtree). */ | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  |  | ||||||
| 	size_t namelen; | 	size_t namelen; | ||||||
| 	unsigned mode; | 	unsigned mode; | ||||||
|  |  | ||||||
|  | 	/* is the length of the full path for the current tree. */ | ||||||
| 	size_t pathlen; | 	size_t pathlen; | ||||||
|  |  | ||||||
| 	struct pathspec *pathspec; | 	struct pathspec *pathspec; | ||||||
|  |  | ||||||
|  | 	/* can be used by callbacks to maintain directory-file conflicts. */ | ||||||
| 	unsigned long df_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; | 	traverse_callback_t fn; | ||||||
|  |  | ||||||
|  | 	/* can be anything the `fn` callback would want to use. */ | ||||||
| 	void *data; | 	void *data; | ||||||
|  |  | ||||||
|  | 	/* tells whether to stop at the first error or not. */ | ||||||
| 	int show_all_errors; | 	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 *); | 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, | char *make_traverse_path(char *path, size_t pathlen, const struct traverse_info *info, | ||||||
| 			 const char *name, size_t namelen); | 			 const char *name, size_t namelen); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Convenience wrapper to `make_traverse_path` into a strbuf. | ||||||
|  |  */ | ||||||
| void strbuf_make_traverse_path(struct strbuf *out, | void strbuf_make_traverse_path(struct strbuf *out, | ||||||
| 			       const struct traverse_info *info, | 			       const struct traverse_info *info, | ||||||
| 			       const char *name, size_t namelen); | 			       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); | 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, | static inline size_t traverse_path_len(const struct traverse_info *info, | ||||||
| 				       size_t namelen) | 				       size_t namelen) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano