matrix:
include:
+ - env: Windows
+ os: linux
+ compiler:
+ addons:
+ before_install:
+ before_script:
+ script:
+ - >
+ test "$TRAVIS_REPO_SLUG" != "git/git" ||
+ ci/run-windows-build.sh $TRAVIS_BRANCH $(git rev-parse HEAD)
+ after_failure:
- env: Linux32
os: linux
services:
we can safely accept them case insensitively without introducing
ambiguity or confusion to solve this.
+ * "git tag/branch/for-each-ref" family of commands long allowed to
+ filter the refs by "--contains X" (show only the refs that are
+ descendants of X), "--merged X" (show only the refs that are
+ ancestors of X), "--no-merged X" (show only the refs that are not
+ ancestors of X). One curious omission, "--no-contains X" (show
+ only the refs that are not descendants of X) has been added to
+ them.
+
+ * The default behaviour of "git log" in an interactive session has
+ been changed to enable "--decorate".
+
Performance, Internal Implementation, Development Support etc.
* Some debugging output from "git describe" were marked for l10n,
but some weren't. Mark missing ones for l10n.
+ * Define a new task in .travis.yml that triggers a test session on
+ Windows run elsewhere.
Also contains various documentation updates and code clean-ups.
certificate; this has been fixed.
(merge f2214dede9 bc/push-cert-receive-fix later to maint).
+ * Update error handling for codepath that deals with corrupt loose
+ objects.
+ (merge 51054177b3 jk/loose-object-info-report-error later to maint).
+
+ * "git diff --submodule=diff" learned to work better in a project
+ with a submodule that in turn has its own submodules.
+ (merge 17b254cda6 sb/show-diff-for-submodule-in-diff-fix later to maint).
+
+ * Update the build dependency so that an update to /usr/bin/perl
+ etc. result in recomputation of perl.mak file.
+ (merge c59c4939c2 ab/regen-perl-mak-with-different-perl later to maint).
+
* Other minor doc, test and build updates and code cleanups.
(merge df2a6e38b7 jk/pager-in-use later to maint).
(merge 75ec4a6cb0 ab/branch-list-doc later to maint).
(merge 4473060bc2 ab/test-readme-updates later to maint).
(merge 48a96972fd ab/doc-submitting later to maint).
(merge f5c2bc2b96 jk/make-coccicheck-detect-errors later to maint).
+ (merge c105f563d1 cc/untracked later to maint).
+ (merge 8668976b53 jc/unused-symbols later to maint).
+ (merge fba275dc93 jc/bs-t-is-not-a-tab-for-sed later to maint).
+ (merge be6ed145de mm/ls-files-s-doc later to maint).
+ (merge 60b091c679 qp/bisect-docfix later to maint).
mix "good" and "bad" with "old" and "new" in a single session.)
In this more general usage, you provide `git bisect` with a "new"
-commit has some property and an "old" commit that doesn't have that
+commit that has some property and an "old" commit that doesn't have that
property. Each time `git bisect` checks out a commit, you test if that
commit has the property. If it does, mark the commit as "new";
otherwise, mark it as "old". When the bisection is done, `git bisect`
[verse]
'git branch' [--color[=<when>] | --no-color] [-r | -a]
[--list] [-v [--abbrev=<length> | --no-abbrev]]
- [--column[=<options>] | --no-column]
- [(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>]
+ [--column[=<options>] | --no-column] [--sort=<key>]
+ [(--merged | --no-merged) [<commit>]]
+ [--contains [<commit]] [--no-contains [<commit>]]
[--points-at <object>] [--format=<format>] [<pattern>...]
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
With `--contains`, shows only the branches that contain the named commit
(in other words, the branches whose tip commits are descendants of the
-named commit). With `--merged`, only branches merged into the named
-commit (i.e. the branches whose tip commits are reachable from the named
-commit) will be listed. With `--no-merged` only branches not merged into
-the named commit will be listed. If the <commit> argument is missing it
-defaults to `HEAD` (i.e. the tip of the current branch).
+named commit), `--no-contains` inverts it. With `--merged`, only branches
+merged into the named commit (i.e. the branches whose tip commits are
+reachable from the named commit) will be listed. With `--no-merged` only
+branches not merged into the named commit will be listed. If the <commit>
+argument is missing it defaults to `HEAD` (i.e. the tip of the current
+branch).
The command's second form creates a new branch head named <branchname>
which points to the current `HEAD`, or <start-point> if given.
Only list branches which contain the specified commit (HEAD
if not specified). Implies `--list`.
+--no-contains [<commit>]::
+ Only list branches which don't contain the specified commit
+ (HEAD if not specified). Implies `--list`.
+
--merged [<commit>]::
Only list branches whose tips are reachable from the
- specified commit (HEAD if not specified). Implies `--list`.
+ specified commit (HEAD if not specified). Implies `--list`,
+ incompatible with `--no-merged`.
--no-merged [<commit>]::
Only list branches whose tips are not reachable from the
- specified commit (HEAD if not specified). Implies `--list`.
+ specified commit (HEAD if not specified). Implies `--list`,
+ incompatible with `--merged`.
<branchname>::
The name of the branch to create or delete.
easier to use the git checkout command with its `-b` option to create
a branch and check it out with a single command.
-The options `--contains`, `--merged` and `--no-merged` serve three related
-but different purposes:
+The options `--contains`, `--no-contains`, `--merged` and `--no-merged`
+serve four related but different purposes:
- `--contains <commit>` is used to find all branches which will need
special attention if <commit> were to be rebased or amended, since those
branches contain the specified <commit>.
+- `--no-contains <commit>` is the inverse of that, i.e. branches that don't
+ contain the specified <commit>.
+
- `--merged` is used to find all branches which can be safely deleted,
since those branches are fully contained by HEAD.
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)...] [--format=<format>] [<pattern>...]
[--points-at <object>] [(--merged | --no-merged) [<object>]]
- [--contains [<object>]]
+ [--contains [<object>]] [--no-contains [<object>]]
DESCRIPTION
-----------
--merged [<object>]::
Only list refs whose tips are reachable from the
- specified commit (HEAD if not specified).
+ specified commit (HEAD if not specified),
+ incompatible with `--no-merged`.
--no-merged [<object>]::
Only list refs whose tips are not reachable from the
- specified commit (HEAD if not specified).
+ specified commit (HEAD if not specified),
+ incompatible with `--merged`.
--contains [<object>]::
Only list refs which contain the specified commit (HEAD if not
specified).
+--no-contains [<object>]::
+ Only list refs which don't contain the specified commit (HEAD
+ if not specified).
+
--ignore-case::
Sorting and filtering refs are case insensitive.
-s::
--stage::
- Show staged contents' object name, mode bits and stage number in the output.
+ Show staged contents' mode bits, object name and stage number in the output.
--directory::
If a whole directory is classified as "other", show just its
! ! ignored
-------------------------------------------------
+Submodules have more state and instead report
+ M the submodule has a different HEAD than
+ recorded in the index
+ m the submodule has modified content
+ ? the submodule has untracked files
+since modified content or untracked files in a submodule cannot be added
+via `git add` in the superproject to prepare a commit.
+
+'m' and '?' are applied recursively. For example if a nested submodule
+in a submodule contains an untracked file, this is reported as '?' as well.
+
If -b is used the short-format status is preceded by a line
## branchname tracking info
characters are not specially formatted; no quoting or
backslash-escaping is performed.
+Any submodule changes are reported as modified `M` instead of `m` or single `?`.
+
Porcelain Format Version 2
~~~~~~~~~~~~~~~~~~~~~~~~~~
'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>]
<tagname> [<commit> | <object>]
'git tag' -d <tagname>...
-'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
- [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>]
- [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
+'git tag' [-n[<num>]] -l [--contains <commit>] [--contains <commit>]
+ [--points-at <object>] [--column[=<options>] | --no-column]
+ [--create-reflog] [--sort=<key>] [--format=<format>]
+ [--[no-]merged [<commit>]] [<pattern>...]
'git tag' -v [--format=<format>] <tagname>...
DESCRIPTION
-n<num>::
<num> specifies how many lines from the annotation, if any,
- are printed when using -l.
- The default is not to print any annotation lines.
- If no number is given to `-n`, only the first line is printed.
- If the tag is not annotated, the commit message is displayed instead.
-
--l <pattern>::
---list <pattern>::
- List tags with names that match the given pattern (or all if no
- pattern is given). Running "git tag" without arguments also
- lists all tags. The pattern is a shell wildcard (i.e., matched
- using fnmatch(3)). Multiple patterns may be given; if any of
- them matches, the tag is shown.
+ are printed when using -l. Implies `--list`.
++
+The default is not to print any annotation lines.
+If no number is given to `-n`, only the first line is printed.
+If the tag is not annotated, the commit message is displayed instead.
+
+-l::
+--list::
+ List tags. With optional `<pattern>...`, e.g. `git tag --list
+ 'v-*'`, list only the tags that match the pattern(s).
++
+Running "git tag" without arguments also lists all tags. The pattern
+is a shell wildcard (i.e., matched using fnmatch(3)). Multiple
+patterns may be given; if any of them matches, the tag is shown.
++
+This option is implicitly supplied if any other list-like option such
+as `--contains` is provided. See the documentation for each of those
+options for details.
--sort=<key>::
Sort based on the key given. Prefix `-` to sort in
--contains [<commit>]::
Only list tags which contain the specified commit (HEAD if not
- specified).
+ specified). Implies `--list`.
+
+--no-contains [<commit>]::
+ Only list tags which don't contain the specified commit (HEAD if
+ not specified). Implies `--list`.
+
+--merged [<commit>]::
+ Only list tags whose commits are reachable from the specified
+ commit (`HEAD` if not specified), incompatible with `--no-merged`.
+
+--no-merged [<commit>]::
+ Only list tags whose commits are not reachable from the specified
+ commit (`HEAD` if not specified), incompatible with `--merged`.
--points-at <object>::
- Only list tags of the given object.
+ Only list tags of the given object (HEAD if not
+ specified). Implies `--list`.
-m <msg>::
--message=<msg>::
that of linkgit:git-for-each-ref[1]. When unspecified,
defaults to `%(refname:strip=2)`.
---[no-]merged [<commit>]::
- Only list tags whose tips are reachable, or not reachable
- if `--no-merged` is used, from the specified commit (`HEAD`
- if not specified).
-
CONFIGURATION
-------------
By default, 'git tag' in sign-with-default mode (-s) will use your
--- /dev/null
+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_unique`::
+ Efficiently iterate over each unique element of the list,
+ executing the callback function for each one. If the array is
+ not sorted, this function has the side effect of sorting it. If
+ the callback returns a non-zero value, the iteration ends
+ immediately and the callback's return is propagated; otherwise,
+ 0 is returned.
+
+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);
+}
+-----------------------------------------
+++ /dev/null
-sha1-array API
-==============
-
-The sha1-array API provides storage and manipulation of sets of SHA-1
-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 sha1_array`::
-
- A single array of SHA-1 hashes. This should be initialized by
- assignment from `SHA1_ARRAY_INIT`. The `sha1` 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
----------
-
-`sha1_array_append`::
- Add an item to the set. The sha1 will be placed at the end of
- the array (but note that some operations below may lose this
- ordering).
-
-`sha1_array_lookup`::
- Perform a binary search of the array for a specific sha1.
- If found, returns the offset (in number of elements) of the
- sha1. If not found, returns a negative integer. If the array is
- not sorted, this function has the side effect of sorting it.
-
-`sha1_array_clear`::
- Free all memory associated with the array and return it to the
- initial, empty state.
-
-`sha1_array_for_each_unique`::
- Efficiently iterate over each unique element of the list,
- executing the callback function for each one. If the array is
- not sorted, this function has the side effect of sorting it. If
- the callback returns a non-zero value, the iteration ends
- immediately and the callback's return is propagated; otherwise,
- 0 is returned.
-
-Examples
---------
-
------------------------------------------
-int print_callback(const unsigned char sha1[20],
- void *data)
-{
- printf("%s\n", sha1_to_hex(sha1));
- return 0; /* always continue */
-}
-
-void some_func(void)
-{
- struct sha1_array hashes = SHA1_ARRAY_INIT;
- unsigned char sha1[20];
-
- /* Read objects into our set */
- while (read_object_from_stdin(sha1))
- sha1_array_append(&hashes, sha1);
-
- /* Check if some objects are in our set */
- while (read_object_from_stdin(sha1)) {
- if (sha1_array_lookup(&hashes, sha1) >= 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.
- */
- sha1_array_for_each_unique(&hashes, print_callback, NULL);
-}
------------------------------------------
perl/PM.stamp: FORCE
@$(FIND) perl -type f -name '*.pm' | sort >$@+ && \
+ $(PERL_PATH) -V >>$@+ && \
{ cmp $@+ $@ >/dev/null 2>/dev/null || mv $@+ $@; } && \
$(RM) $@+
#include "sha1-array.h"
#include "argv-array.h"
-static struct sha1_array good_revs;
-static struct sha1_array skipped_revs;
+static struct oid_array good_revs;
+static struct oid_array skipped_revs;
static struct object_id *current_bad_oid;
{
struct commit_list *p;
struct commit_dist *array = xcalloc(nr, sizeof(*array));
+ struct strbuf buf = STRBUF_INIT;
int cnt, i;
for (p = list, cnt = 0; p; p = p->next) {
}
QSORT(array, cnt, compare_commit_dist);
for (p = list, i = 0; i < cnt; i++) {
- char buf[100]; /* enough for dist=%d */
struct object *obj = &(array[i].commit->object);
- snprintf(buf, sizeof(buf), "dist=%d", array[i].distance);
- add_name_decoration(DECORATION_NONE, buf, obj);
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "dist=%d", array[i].distance);
+ add_name_decoration(DECORATION_NONE, buf.buf, obj);
p->item = array[i].commit;
p = p->next;
}
if (p)
p->next = NULL;
+ strbuf_release(&buf);
free(array);
return list;
}
current_bad_oid = xmalloc(sizeof(*current_bad_oid));
oidcpy(current_bad_oid, oid);
} else if (starts_with(refname, good_prefix.buf)) {
- sha1_array_append(&good_revs, oid->hash);
+ oid_array_append(&good_revs, oid);
} else if (starts_with(refname, "skip-")) {
- sha1_array_append(&skipped_revs, oid->hash);
+ oid_array_append(&skipped_revs, oid);
}
strbuf_release(&good_prefix);
fclose(fp);
}
-static char *join_sha1_array_hex(struct sha1_array *array, char delim)
+static char *join_sha1_array_hex(struct oid_array *array, char delim)
{
struct strbuf joined_hexs = STRBUF_INIT;
int i;
for (i = 0; i < array->nr; i++) {
- strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));
+ strbuf_addstr(&joined_hexs, oid_to_hex(array->oid + i));
if (i + 1 < array->nr)
strbuf_addch(&joined_hexs, delim);
}
while (list) {
struct commit_list *next = list->next;
list->next = NULL;
- if (0 <= sha1_array_lookup(&skipped_revs,
- list->item->object.oid.hash)) {
+ if (0 <= oid_array_lookup(&skipped_revs, &list->item->object.oid)) {
if (skipped_first && !*skipped_first)
*skipped_first = 1;
/* Move current to tried list */
argv_array_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid));
for (i = 0; i < good_revs.nr; i++)
argv_array_pushf(&rev_argv, good_format,
- sha1_to_hex(good_revs.sha1[i]));
+ oid_to_hex(good_revs.oid + i));
argv_array_push(&rev_argv, "--");
if (read_paths)
read_bisect_paths(&rev_argv);
static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)
{
- char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
+ char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
}
-static struct commit *get_commit_reference(const unsigned char *sha1)
+static struct commit *get_commit_reference(const struct object_id *oid)
{
- struct commit *r = lookup_commit_reference(sha1);
+ struct commit *r = lookup_commit_reference(oid->hash);
if (!r)
- die(_("Not a valid commit name %s"), sha1_to_hex(sha1));
+ die(_("Not a valid commit name %s"), oid_to_hex(oid));
return r;
}
int i, n = 0;
ALLOC_ARRAY(rev, 1 + good_revs.nr);
- rev[n++] = get_commit_reference(current_bad_oid->hash);
+ rev[n++] = get_commit_reference(current_bad_oid);
for (i = 0; i < good_revs.nr; i++)
- rev[n++] = get_commit_reference(good_revs.sha1[i]);
+ rev[n++] = get_commit_reference(good_revs.oid + i);
*rev_nr = n;
return rev;
exit(1);
}
-static void handle_skipped_merge_base(const unsigned char *mb)
+static void handle_skipped_merge_base(const struct object_id *mb)
{
- char *mb_hex = sha1_to_hex(mb);
+ char *mb_hex = oid_to_hex(mb);
char *bad_hex = oid_to_hex(current_bad_oid);
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
for (; result; result = result->next) {
- const unsigned char *mb = result->item->object.oid.hash;
- if (!hashcmp(mb, current_bad_oid->hash)) {
+ const struct object_id *mb = &result->item->object.oid;
+ if (!oidcmp(mb, current_bad_oid)) {
handle_bad_merge_base();
- } else if (0 <= sha1_array_lookup(&good_revs, mb)) {
+ } else if (0 <= oid_array_lookup(&good_revs, mb)) {
continue;
- } else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {
+ } else if (0 <= oid_array_lookup(&skipped_revs, mb)) {
handle_skipped_merge_base(mb);
} else {
printf(_("Bisecting: a merge base must be tested\n"));
- exit(bisect_checkout(mb, no_checkout));
+ exit(bisect_checkout(mb->hash, no_checkout));
}
}
{
struct commit *commit;
unsigned char sha1[20];
- char *real_ref, msg[PATH_MAX + 20];
+ char *real_ref;
struct strbuf ref = STRBUF_INIT;
int forcing = 0;
int dont_change_ref = 0;
die(_("Not a valid branch point: '%s'."), start_name);
hashcpy(sha1, commit->object.oid.hash);
- if (forcing)
- snprintf(msg, sizeof msg, "branch: Reset to %s",
- start_name);
- else if (!dont_change_ref)
- snprintf(msg, sizeof msg, "branch: Created from %s",
- start_name);
-
if (reflog)
log_all_ref_updates = LOG_REFS_NORMAL;
if (!dont_change_ref) {
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
+ char *msg;
+
+ if (forcing)
+ msg = xstrfmt("branch: Reset to %s", start_name);
+ else
+ msg = xstrfmt("branch: Created from %s", start_name);
transaction = ref_transaction_begin(&err);
if (!transaction ||
die("%s", err.buf);
ref_transaction_free(transaction);
strbuf_release(&err);
+ free(msg);
}
if (real_ref && track)
int cnt;
const char *cp;
struct origin *suspect = ent->suspect;
- char hex[GIT_SHA1_HEXSZ + 1];
+ char hex[GIT_MAX_HEXSZ + 1];
oid_to_hex_r(hex, &suspect->commit->object.oid);
printf("%s %d %d %d\n",
const char *cp;
struct origin *suspect = ent->suspect;
struct commit_info ci;
- char hex[GIT_SHA1_HEXSZ + 1];
+ char hex[GIT_MAX_HEXSZ + 1];
int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
get_commit_info(suspect->commit, &ci, 1);
OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"),
FILTER_REFS_REMOTES),
OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only branches that don't contain the commit")),
OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")),
+ OPT_WITHOUT(&filter.no_commit, N_("print only branches that don't contain the commit")),
OPT__ABBREV(&filter.abbrev),
OPT_GROUP(N_("Specific git-branch actions:")),
if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
list = 1;
- if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr)
+ if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
+ filter.no_commit)
list = 1;
if (!!delete + !!rename + !!new_upstream +
struct expand_data *expand;
};
-static int batch_object_cb(const unsigned char sha1[20], void *vdata)
+static int batch_object_cb(const struct object_id *oid, void *vdata)
{
struct object_cb_data *data = vdata;
- hashcpy(data->expand->oid.hash, sha1);
+ oidcpy(&data->expand->oid, oid);
batch_object_write(NULL, data->opt, data->expand);
return 0;
}
const char *path,
void *data)
{
- sha1_array_append(data, oid->hash);
+ oid_array_append(data, oid);
return 0;
}
uint32_t pos,
void *data)
{
- sha1_array_append(data, oid->hash);
+ oid_array_append(data, oid);
return 0;
}
data.info.typep = &data.type;
if (opt->all_objects) {
- struct sha1_array sa = SHA1_ARRAY_INIT;
+ struct oid_array sa = OID_ARRAY_INIT;
struct object_cb_data cb;
for_each_loose_object(batch_loose_object, &sa, 0);
cb.opt = opt;
cb.expand = &data;
- sha1_array_for_each_unique(&sa, batch_object_cb, &cb);
+ oid_array_for_each_unique(&sa, batch_object_cb, &cb);
- sha1_array_clear(&sa);
+ oid_array_clear(&sa);
return 0;
}
static const char *unique_tracking_name(const char *name, struct object_id *oid)
{
struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 };
- char src_ref[PATH_MAX];
- snprintf(src_ref, PATH_MAX, "refs/heads/%s", name);
- cb_data.src_ref = src_ref;
+ cb_data.src_ref = xstrfmt("refs/heads/%s", name);
cb_data.dst_oid = oid;
for_each_remote(check_tracking_name, &cb_data);
+ free(cb_data.src_ref);
if (cb_data.unique)
return cb_data.dst_ref;
free(cb_data.dst_ref);
#define DIFF_NO_INDEX_IMPLICIT 2
struct blobinfo {
- unsigned char sha1[20];
+ struct object_id oid;
const char *name;
unsigned mode;
};
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
- const unsigned char *old_sha1,
- const unsigned char *new_sha1,
- int old_sha1_valid,
- int new_sha1_valid,
+ const struct object_id *old_oid,
+ const struct object_id *new_oid,
+ int old_oid_valid,
+ int new_oid_valid,
const char *old_name,
const char *new_name)
{
struct diff_filespec *one, *two;
- if (!is_null_sha1(old_sha1) && !is_null_sha1(new_sha1) &&
- !hashcmp(old_sha1, new_sha1) && (old_mode == new_mode))
+ if (!is_null_oid(old_oid) && !is_null_oid(new_oid) &&
+ !oidcmp(old_oid, new_oid) && (old_mode == new_mode))
return;
if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
SWAP(old_mode, new_mode);
- SWAP(old_sha1, new_sha1);
+ SWAP(old_oid, new_oid);
SWAP(old_name, new_name);
}
one = alloc_filespec(old_name);
two = alloc_filespec(new_name);
- fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
- fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
+ fill_filespec(one, old_oid->hash, old_oid_valid, old_mode);
+ fill_filespec(two, new_oid->hash, new_oid_valid, new_mode);
diff_queue(&diff_queued_diff, one, two);
}
stuff_change(&revs->diffopt,
blob[0].mode, canon_mode(st.st_mode),
- blob[0].sha1, null_sha1,
+ &blob[0].oid, &null_oid,
1, 0,
path, path);
diffcore_std(&revs->diffopt);
stuff_change(&revs->diffopt,
blob[0].mode, blob[1].mode,
- blob[0].sha1, blob[1].sha1,
+ &blob[0].oid, &blob[1].oid,
1, 1,
blob[0].name, blob[1].name);
diffcore_std(&revs->diffopt);
struct object_array_entry *ent0,
struct object_array_entry *ent1)
{
- const unsigned char *(sha1[2]);
+ const struct object_id *(oid[2]);
int swap = 0;
if (argc > 1)
*/
if (ent1->item->flags & UNINTERESTING)
swap = 1;
- sha1[swap] = ent0->item->oid.hash;
- sha1[1 - swap] = ent1->item->oid.hash;
- diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
+ oid[swap] = &ent0->item->oid;
+ oid[1 - swap] = &ent1->item->oid;
+ diff_tree_sha1(oid[0]->hash, oid[1]->hash, "", &revs->diffopt);
log_tree_diff_flush(revs);
return 0;
}
struct object_array_entry *ent,
int ents)
{
- struct sha1_array parents = SHA1_ARRAY_INIT;
+ struct oid_array parents = OID_ARRAY_INIT;
int i;
if (argc > 1)
if (!revs->dense_combined_merges && !revs->combine_merges)
revs->dense_combined_merges = revs->combine_merges = 1;
for (i = 1; i < ents; i++)
- sha1_array_append(&parents, ent[i].item->oid.hash);
+ oid_array_append(&parents, &ent[i].item->oid);
diff_tree_combined(ent[0].item->oid.hash, &parents,
revs->dense_combined_merges, revs);
- sha1_array_clear(&parents);
+ oid_array_clear(&parents);
return 0;
}
} else if (obj->type == OBJ_BLOB) {
if (2 <= blobs)
die(_("more than two blobs given: '%s'"), name);
- hashcpy(blob[blobs].sha1, obj->oid.hash);
+ hashcpy(blob[blobs].oid.hash, obj->oid.hash);
blob[blobs].name = name;
blob[blobs].mode = entry->mode;
blobs++;
return data;
}
+static int checkout_path(unsigned mode, struct object_id *oid,
+ const char *path, const struct checkout *state)
+{
+ struct cache_entry *ce;
+ int ret;
+
+ ce = make_cache_entry(mode, oid->hash, path, 0, 0);
+ ret = checkout_entry(ce, state, NULL);
+
+ free(ce);
+ return ret;
+}
+
static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
int argc, const char **argv)
{
struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT;
struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT;
struct strbuf wtdir = STRBUF_INIT;
+ char *lbase_dir, *rbase_dir;
size_t ldir_len, rdir_len, wtdir_len;
- struct cache_entry *ce = xcalloc(1, sizeof(ce) + PATH_MAX + 1);
const char *workdir, *tmp;
int ret = 0, i;
FILE *fp;
memset(&wtindex, 0, sizeof(wtindex));
memset(&lstate, 0, sizeof(lstate));
- lstate.base_dir = ldir.buf;
+ lstate.base_dir = lbase_dir = xstrdup(ldir.buf);
lstate.base_dir_len = ldir.len;
lstate.force = 1;
memset(&rstate, 0, sizeof(rstate));
- rstate.base_dir = rdir.buf;
+ rstate.base_dir = rbase_dir = xstrdup(rdir.buf);
rstate.base_dir_len = rdir.len;
rstate.force = 1;
struct object_id loid, roid;
char status;
const char *src_path, *dst_path;
- size_t src_path_len, dst_path_len;
if (starts_with(info.buf, "::"))
die(N_("combined diff formats('-c' and '--cc') are "
if (strbuf_getline_nul(&lpath, fp))
break;
src_path = lpath.buf;
- src_path_len = lpath.len;
i++;
if (status != 'C' && status != 'R') {
dst_path = src_path;
- dst_path_len = src_path_len;
} else {
if (strbuf_getline_nul(&rpath, fp))
break;
dst_path = rpath.buf;
- dst_path_len = rpath.len;
}
if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) {
}
if (lmode && status != 'C') {
- ce->ce_mode = lmode;
- oidcpy(&ce->oid, &loid);
- strcpy(ce->name, src_path);
- ce->ce_namelen = src_path_len;
- if (checkout_entry(ce, &lstate, NULL))
+ if (checkout_path(lmode, &loid, src_path, &lstate))
return error("could not write '%s'", src_path);
}
hashmap_add(&working_tree_dups, entry);
if (!use_wt_file(workdir, dst_path, &roid)) {
- ce->ce_mode = rmode;
- oidcpy(&ce->oid, &roid);
- strcpy(ce->name, dst_path);
- ce->ce_namelen = dst_path_len;
- if (checkout_entry(ce, &rstate, NULL))
+ if (checkout_path(rmode, &roid, dst_path, &rstate))
return error("could not write '%s'",
dst_path);
} else if (!is_null_oid(&roid)) {
exit_cleanup(tmpdir, rc);
finish:
- free(ce);
+ free(lbase_dir);
+ free(rbase_dir);
strbuf_release(&ldir);
strbuf_release(&rdir);
strbuf_release(&wtdir);
char **pack_lockfile_ptr = NULL;
struct child_process *conn;
struct fetch_pack_args args;
- struct sha1_array shallow = SHA1_ARRAY_INIT;
+ struct oid_array shallow = OID_ARRAY_INIT;
struct string_list deepen_not = STRING_LIST_INIT_DUP;
packet_trace_identity("fetch-pack");
struct ref *ref,
int check_old)
{
- char msg[1024];
+ char *msg;
char *rla = getenv("GIT_REFLOG_ACTION");
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
return 0;
if (!rla)
rla = default_rla.buf;
- snprintf(msg, sizeof(msg), "%s: %s", rla, action);
+ msg = xstrfmt("%s: %s", rla, action);
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_free(transaction);
strbuf_release(&err);
+ free(msg);
return 0;
fail:
ref_transaction_free(transaction);
error("%s", err.buf);
strbuf_release(&err);
+ free(msg);
return df_conflict ? STORE_REF_ERROR_DF_CONFLICT
: STORE_REF_ERROR_OTHER;
}
if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
(recurse_submodules != RECURSE_SUBMODULES_ON))
- check_for_new_submodule_commits(ref->new_oid.hash);
+ check_for_new_submodule_commits(&ref->new_oid);
r = s_update_ref(msg, ref, 0);
format_display(display, r ? '!' : '*', what,
r ? _("unable to update local ref") : NULL,
strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
(recurse_submodules != RECURSE_SUBMODULES_ON))
- check_for_new_submodule_commits(ref->new_oid.hash);
+ check_for_new_submodule_commits(&ref->new_oid);
r = s_update_ref("fast-forward", ref, 1);
format_display(display, r ? '!' : ' ', quickref.buf,
r ? _("unable to update local ref") : NULL,
strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
(recurse_submodules != RECURSE_SUBMODULES_ON))
- check_for_new_submodule_commits(ref->new_oid.hash);
+ check_for_new_submodule_commits(&ref->new_oid);
r = s_update_ref("forced-update", ref, 1);
format_display(display, r ? '!' : '+', quickref.buf,
r ? _("unable to update local ref") : _("forced update"),
static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [<options>] [<pattern>]"),
N_("git for-each-ref [--points-at <object>]"),
- N_("git for-each-ref [(--merged | --no-merged) [<object>]]"),
- N_("git for-each-ref [--contains [<object>]]"),
+ N_("git for-each-ref [(--merged | --no-merged) [<commit>]]"),
+ N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
NULL
};
OPT_MERGED(&filter, N_("print only refs that are merged")),
OPT_NO_MERGED(&filter, N_("print only refs that are not merged")),
OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_END(),
};
* distributed, we can check only one and get a reasonable
* estimate.
*/
- char path[PATH_MAX];
- const char *objdir = get_object_directory();
DIR *dir;
struct dirent *ent;
int auto_threshold;
if (gc_auto_threshold <= 0)
return 0;
- if (sizeof(path) <= snprintf(path, sizeof(path), "%s/17", objdir)) {
- warning(_("insanely long object directory %.*s"), 50, objdir);
- return 0;
- }
- dir = opendir(path);
+ dir = opendir(git_path("objects/17"));
if (!dir)
return 0;
if (from_stdin) {
input_fd = 0;
if (!pack_name) {
- static char tmp_file[PATH_MAX];
- output_fd = odb_mkstemp(tmp_file, sizeof(tmp_file),
+ struct strbuf tmp_file = STRBUF_INIT;
+ output_fd = odb_mkstemp(&tmp_file,
"pack/tmp_pack_XXXXXX");
- pack_name = xstrdup(tmp_file);
- } else
+ pack_name = strbuf_detach(&tmp_file, NULL);
+ } else {
output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
- if (output_fd < 0)
- die_errno(_("unable to create '%s'"), pack_name);
+ if (output_fd < 0)
+ die_errno(_("unable to create '%s'"), pack_name);
+ }
nothread_data.pack_fd = output_fd;
} else {
input_fd = open(pack_name, O_RDONLY);
unsigned long has_size;
read_lock();
has_type = sha1_object_info(sha1, &has_size);
+ if (has_type < 0)
+ die(_("cannot read existing object info %s"), sha1_to_hex(sha1));
if (has_type != type || has_size != size)
die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1));
has_data = read_sha1_file(sha1, &has_type, &has_size);
if (!from_stdin) {
printf("%s\n", sha1_to_hex(sha1));
} else {
- char buf[48];
- int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
- report, sha1_to_hex(sha1));
- write_or_die(1, buf, len);
+ struct strbuf buf = STRBUF_INIT;
+
+ strbuf_addf(&buf, "%s\t%s\n", report, sha1_to_hex(sha1));
+ write_or_die(1, buf.buf, buf.len);
+ strbuf_release(&buf);
/*
* Let's just mimic git-unpack-objects here and write
struct string_list args;
};
+static int auto_decoration_style(void)
+{
+ return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0;
+}
+
static int parse_decoration_style(const char *var, const char *value)
{
switch (git_config_maybe_bool(var, value)) {
else if (!strcmp(value, "short"))
return DECORATE_SHORT_REFS;
else if (!strcmp(value, "auto"))
- return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0;
+ return auto_decoration_style();
return -1;
}
if (decoration_style < 0)
decoration_style = 0; /* maybe warn? */
return 0;
+ } else {
+ decoration_style = auto_decoration_style();
}
if (!strcmp(var, "log.showroot")) {
default_show_root = git_config_bool(var, value);
static int tail_match(const char **pattern, const char *path)
{
const char *p;
- char pathbuf[PATH_MAX];
+ char *pathbuf;
if (!pattern)
return 1; /* no restriction */
- if (snprintf(pathbuf, sizeof(pathbuf), "/%s", path) > sizeof(pathbuf))
- return error("insanely long ref %.*s...", 20, path);
+ pathbuf = xstrfmt("/%s", path);
while ((p = *(pattern++)) != NULL) {
- if (!wildmatch(p, pathbuf, 0, NULL))
+ if (!wildmatch(p, pathbuf, 0, NULL)) {
+ free(pathbuf);
return 1;
+ }
}
+ free(pathbuf);
return 0;
}
{
int found;
const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
- char hexbuf[4][GIT_SHA1_HEXSZ + 1];
+ char hexbuf[4][GIT_MAX_HEXSZ + 1];
char ownbuf[4][60];
if (pos >= active_nr)
if (verify_signatures) {
for (p = remoteheads; p; p = p->next) {
struct commit *commit = p->item;
- char hex[GIT_SHA1_HEXSZ + 1];
+ char hex[GIT_MAX_HEXSZ + 1];
struct signature_check signature_check;
memset(&signature_check, 0, sizeof(signature_check));
return NULL;
}
-/* returns a static buffer */
-static const char *get_rev_name(const struct object *o)
+/* may return a constant string or use "buf" as scratch space */
+static const char *get_rev_name(const struct object *o, struct strbuf *buf)
{
- static char buffer[1024];
struct rev_name *n;
struct commit *c;
int len = strlen(n->tip_name);
if (len > 2 && !strcmp(n->tip_name + len - 2, "^0"))
len -= 2;
- snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name,
- n->generation);
-
- return buffer;
+ strbuf_reset(buf);
+ strbuf_addf(buf, "%.*s~%d", len, n->tip_name, n->generation);
+ return buf->buf;
}
}
{
const char *name;
const struct object_id *oid = &obj->oid;
+ struct strbuf buf = STRBUF_INIT;
if (!name_only)
printf("%s ", caller_name ? caller_name : oid_to_hex(oid));
- name = get_rev_name(obj);
+ name = get_rev_name(obj, &buf);
if (name)
printf("%s\n", name);
else if (allow_undefined)
printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
else
die("cannot describe '%s'", oid_to_hex(oid));
+ strbuf_release(&buf);
}
static char const * const name_rev_usage[] = {
static void name_rev_line(char *p, struct name_ref_data *data)
{
+ struct strbuf buf = STRBUF_INIT;
int forty = 0;
char *p_start;
for (p_start = p; *p; p++) {
struct object *o =
lookup_object(sha1);
if (o)
- name = get_rev_name(o);
+ name = get_rev_name(o, &buf);
}
*(p+1) = c;
/* flush */
if (p_start != p)
fwrite(p_start, p - p_start, 1, stdout);
+
+ strbuf_release(&buf);
}
int cmd_name_rev(int argc, const char **argv, const char *prefix)
struct notes_tree *t;
unsigned char object[20], new_note[20];
const unsigned char *note;
- char logmsg[100];
+ char *logmsg;
const char * const *usage;
struct note_data d = { 0, 0, NULL, STRBUF_INIT };
struct option options[] = {
write_note_data(&d, new_note);
if (add_note(t, object, new_note, combine_notes_overwrite))
die("BUG: combine_notes_overwrite failed");
- snprintf(logmsg, sizeof(logmsg), "Notes added by 'git notes %s'",
- argv[0]);
+ logmsg = xstrfmt("Notes added by 'git notes %s'", argv[0]);
} else {
fprintf(stderr, _("Removing note for object %s\n"),
sha1_to_hex(object));
remove_note(t, object);
- snprintf(logmsg, sizeof(logmsg), "Notes removed by 'git notes %s'",
- argv[0]);
+ logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]);
}
commit_notes(t, logmsg);
+ free(logmsg);
free_note_data(&d);
free_notes(t);
return 0;
*
* This is filled by get_object_list.
*/
-static struct sha1_array recent_objects;
+static struct oid_array recent_objects;
-static int loosened_object_can_be_discarded(const unsigned char *sha1,
+static int loosened_object_can_be_discarded(const struct object_id *oid,
unsigned long mtime)
{
if (!unpack_unreachable_expiration)
return 0;
if (mtime > unpack_unreachable_expiration)
return 0;
- if (sha1_array_lookup(&recent_objects, sha1) >= 0)
+ if (oid_array_lookup(&recent_objects, oid) >= 0)
return 0;
return 1;
}
{
struct packed_git *p;
uint32_t i;
- const unsigned char *sha1;
+ struct object_id oid;
for (p = packed_git; p; p = p->next) {
if (!p->pack_local || p->pack_keep)
die("cannot open pack index");
for (i = 0; i < p->num_objects; i++) {
- sha1 = nth_packed_object_sha1(p, i);
- if (!packlist_find(&to_pack, sha1, NULL) &&
- !has_sha1_pack_kept_or_nonlocal(sha1) &&
- !loosened_object_can_be_discarded(sha1, p->mtime))
- if (force_object_loose(sha1, p->mtime))
+ nth_packed_object_oid(&oid, p, i);
+ if (!packlist_find(&to_pack, oid.hash, NULL) &&
+ !has_sha1_pack_kept_or_nonlocal(oid.hash) &&
+ !loosened_object_can_be_discarded(&oid, p->mtime))
+ if (force_object_loose(oid.hash, p->mtime))
die("unable to force loose object");
}
}
const char *name,
void *data)
{
- sha1_array_append(&recent_objects, obj->oid.hash);
+ oid_array_append(&recent_objects, &obj->oid);
}
static void record_recent_commit(struct commit *commit, void *data)
{
- sha1_array_append(&recent_objects, commit->object.oid.hash);
+ oid_array_append(&recent_objects, &commit->object.oid);
}
static void get_object_list(int ac, const char **av)
if (unpack_unreachable)
loosen_unused_packed_objects(&revs);
- sha1_array_clear(&recent_objects);
+ oid_array_clear(&recent_objects);
}
static int option_parse_index_version(const struct option *opt,
static void flush_one_hunk(struct object_id *result, git_SHA_CTX *ctx)
{
- unsigned char hash[GIT_SHA1_RAWSZ];
+ unsigned char hash[GIT_MAX_RAWSZ];
unsigned short carry = 0;
int i;
* Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
* into merge_heads.
*/
-static void get_merge_heads(struct sha1_array *merge_heads)
+static void get_merge_heads(struct oid_array *merge_heads)
{
const char *filename = git_path("FETCH_HEAD");
FILE *fp;
struct strbuf sb = STRBUF_INIT;
- unsigned char sha1[GIT_SHA1_RAWSZ];
+ struct object_id oid;
if (!(fp = fopen(filename, "r")))
die_errno(_("could not open '%s' for reading"), filename);
while (strbuf_getline_lf(&sb, fp) != EOF) {
- if (get_sha1_hex(sb.buf, sha1))
+ if (get_oid_hex(sb.buf, &oid))
continue; /* invalid line: does not start with SHA1 */
if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t"))
continue; /* ref is not-for-merge */
- sha1_array_append(merge_heads, sha1);
+ oid_array_append(merge_heads, &oid);
}
fclose(fp);
strbuf_release(&sb);
/**
* "Pulls into void" by branching off merge_head.
*/
-static int pull_into_void(const unsigned char *merge_head,
- const unsigned char *curr_head)
+static int pull_into_void(const struct object_id *merge_head,
+ const struct object_id *curr_head)
{
/*
* Two-way merge: we treat the index as based on an empty tree,
* index/worktree changes that the user already made on the unborn
* branch.
*/
- if (checkout_fast_forward(EMPTY_TREE_SHA1_BIN, merge_head, 0))
+ if (checkout_fast_forward(EMPTY_TREE_SHA1_BIN, merge_head->hash, 0))
return 1;
- if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
+ if (update_ref("initial pull", "HEAD", merge_head->hash, curr_head->hash, 0, UPDATE_REFS_DIE_ON_ERR))
return 1;
return 0;
* current branch forked from its remote tracking branch. Returns 0 on success,
* -1 on failure.
*/
-static int get_rebase_fork_point(unsigned char *fork_point, const char *repo,
+static int get_rebase_fork_point(struct object_id *fork_point, const char *repo,
const char *refspec)
{
int ret;
if (ret)
goto cleanup;
- ret = get_sha1_hex(sb.buf, fork_point);
+ ret = get_oid_hex(sb.buf, fork_point);
if (ret)
goto cleanup;
* Sets merge_base to the octopus merge base of curr_head, merge_head and
* fork_point. Returns 0 if a merge base is found, 1 otherwise.
*/
-static int get_octopus_merge_base(unsigned char *merge_base,
- const unsigned char *curr_head,
- const unsigned char *merge_head,
- const unsigned char *fork_point)
+static int get_octopus_merge_base(struct object_id *merge_base,
+ const struct object_id *curr_head,
+ const struct object_id *merge_head,
+ const struct object_id *fork_point)
{
struct commit_list *revs = NULL, *result;
- commit_list_insert(lookup_commit_reference(curr_head), &revs);
- commit_list_insert(lookup_commit_reference(merge_head), &revs);
- if (!is_null_sha1(fork_point))
- commit_list_insert(lookup_commit_reference(fork_point), &revs);
+ commit_list_insert(lookup_commit_reference(curr_head->hash), &revs);
+ commit_list_insert(lookup_commit_reference(merge_head->hash), &revs);
+ if (!is_null_oid(fork_point))
+ commit_list_insert(lookup_commit_reference(fork_point->hash), &revs);
result = reduce_heads(get_octopus_merge_bases(revs));
free_commit_list(revs);
if (!result)
return 1;
- hashcpy(merge_base, result->item->object.oid.hash);
+ oidcpy(merge_base, &result->item->object.oid);
return 0;
}
* fork point calculated by get_rebase_fork_point(), runs git-rebase with the
* appropriate arguments and returns its exit status.
*/
-static int run_rebase(const unsigned char *curr_head,
- const unsigned char *merge_head,
- const unsigned char *fork_point)
+static int run_rebase(const struct object_id *curr_head,
+ const struct object_id *merge_head,
+ const struct object_id *fork_point)
{
int ret;
- unsigned char oct_merge_base[GIT_SHA1_RAWSZ];
+ struct object_id oct_merge_base;
struct argv_array args = ARGV_ARRAY_INIT;
- if (!get_octopus_merge_base(oct_merge_base, curr_head, merge_head, fork_point))
- if (!is_null_sha1(fork_point) && !hashcmp(oct_merge_base, fork_point))
+ if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point))
+ if (!is_null_oid(fork_point) && !oidcmp(&oct_merge_base, fork_point))
fork_point = NULL;
argv_array_push(&args, "rebase");
warning(_("ignoring --verify-signatures for rebase"));
argv_array_push(&args, "--onto");
- argv_array_push(&args, sha1_to_hex(merge_head));
+ argv_array_push(&args, oid_to_hex(merge_head));
- if (fork_point && !is_null_sha1(fork_point))
- argv_array_push(&args, sha1_to_hex(fork_point));
+ if (fork_point && !is_null_oid(fork_point))
+ argv_array_push(&args, oid_to_hex(fork_point));
else
- argv_array_push(&args, sha1_to_hex(merge_head));
+ argv_array_push(&args, oid_to_hex(merge_head));
ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
int cmd_pull(int argc, const char **argv, const char *prefix)
{
const char *repo, **refspecs;
- struct sha1_array merge_heads = SHA1_ARRAY_INIT;
- unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ];
- unsigned char rebase_fork_point[GIT_SHA1_RAWSZ];
+ struct oid_array merge_heads = OID_ARRAY_INIT;
+ struct object_id orig_head, curr_head;
+ struct object_id rebase_fork_point;
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
if (file_exists(git_path("MERGE_HEAD")))
die_conclude_merge();
- if (get_sha1("HEAD", orig_head))
- hashclr(orig_head);
+ if (get_oid("HEAD", &orig_head))
+ oidclr(&orig_head);
if (!opt_rebase && opt_autostash != -1)
die(_("--[no-]autostash option is only valid with --rebase."));
if (opt_autostash != -1)
autostash = opt_autostash;
- if (is_null_sha1(orig_head) && !is_cache_unborn())
+ if (is_null_oid(&orig_head) && !is_cache_unborn())
die(_("Updating an unborn branch with changes added to the index."));
if (!autostash)
require_clean_work_tree(N_("pull with rebase"),
_("please commit or stash them."), 1, 0);
- if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
- hashclr(rebase_fork_point);
+ if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
+ oidclr(&rebase_fork_point);
}
if (run_fetch(repo, refspecs))
if (opt_dry_run)
return 0;
- if (get_sha1("HEAD", curr_head))
- hashclr(curr_head);
+ if (get_oid("HEAD", &curr_head))
+ oidclr(&curr_head);
- if (!is_null_sha1(orig_head) && !is_null_sha1(curr_head) &&
- hashcmp(orig_head, curr_head)) {
+ if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) &&
+ oidcmp(&orig_head, &curr_head)) {
/*
* The fetch involved updating the current branch.
*
warning(_("fetch updated the current branch head.\n"
"fast-forwarding your working tree from\n"
- "commit %s."), sha1_to_hex(orig_head));
+ "commit %s."), oid_to_hex(&orig_head));
- if (checkout_fast_forward(orig_head, curr_head, 0))
+ if (checkout_fast_forward(orig_head.hash, curr_head.hash, 0))
die(_("Cannot fast-forward your working tree.\n"
"After making sure that you saved anything precious from\n"
"$ git diff %s\n"
"output, run\n"
"$ git reset --hard\n"
- "to recover."), sha1_to_hex(orig_head));
+ "to recover."), oid_to_hex(&orig_head));
}
get_merge_heads(&merge_heads);
if (!merge_heads.nr)
die_no_merge_candidates(repo, refspecs);
- if (is_null_sha1(orig_head)) {
+ if (is_null_oid(&orig_head)) {
if (merge_heads.nr > 1)
die(_("Cannot merge multiple branches into empty head."));
- return pull_into_void(*merge_heads.sha1, curr_head);
+ return pull_into_void(merge_heads.oid, &curr_head);
}
if (opt_rebase && merge_heads.nr > 1)
die(_("Cannot rebase onto multiple branches."));
struct commit_list *list = NULL;
struct commit *merge_head, *head;
- head = lookup_commit_reference(orig_head);
+ head = lookup_commit_reference(orig_head.hash);
commit_list_insert(head, &list);
- merge_head = lookup_commit_reference(merge_heads.sha1[0]);
+ merge_head = lookup_commit_reference(merge_heads.oid[0].hash);
if (is_descendant_of(merge_head, list)) {
/* we can fast-forward this without invoking rebase */
opt_ff = "--ff-only";
return run_merge();
}
- return run_rebase(curr_head, *merge_heads.sha1, rebase_fork_point);
+ return run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
} else {
return run_merge();
}
return git_default_config(var, value, cb);
}
-static void show_ref(const char *path, const unsigned char *sha1)
+static void show_ref(const char *path, const struct object_id *oid)
{
if (sent_capabilities) {
- packet_write_fmt(1, "%s %s\n", sha1_to_hex(sha1), path);
+ packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), path);
} else {
struct strbuf cap = STRBUF_INIT;
strbuf_addstr(&cap, " push-options");
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
packet_write_fmt(1, "%s %s%c%s\n",
- sha1_to_hex(sha1), path, 0, cap.buf);
+ oid_to_hex(oid), path, 0, cap.buf);
strbuf_release(&cap);
sent_capabilities = 1;
}
} else {
oidset_insert(seen, oid);
}
- show_ref(path, oid->hash);
+ show_ref(path, oid);
return 0;
}
if (oidset_insert(seen, oid))
return;
- show_ref(".have", oid->hash);
+ show_ref(".have", oid);
}
static void write_head_info(void)
for_each_alternate_ref(show_one_alternate_ref, &seen);
oidset_clear(&seen);
if (!sent_capabilities)
- show_ref("capabilities^{}", null_sha1);
+ show_ref("capabilities^{}", &null_oid);
advertise_shallow_grafts(1);
unsigned int skip_update:1,
did_not_exist:1;
int index;
- unsigned char old_sha1[20];
- unsigned char new_sha1[20];
+ struct object_id old_oid;
+ struct object_id new_oid;
char ref_name[FLEX_ARRAY]; /* more */
};
return -1; /* EOF */
strbuf_reset(&state->buf);
strbuf_addf(&state->buf, "%s %s %s\n",
- sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1),
+ oid_to_hex(&cmd->old_oid), oid_to_hex(&cmd->new_oid),
cmd->ref_name);
state->cmd = cmd->next;
if (bufp) {
return 0;
argv[1] = cmd->ref_name;
- argv[2] = sha1_to_hex(cmd->old_sha1);
- argv[3] = sha1_to_hex(cmd->new_sha1);
+ argv[2] = oid_to_hex(&cmd->old_oid);
+ argv[3] = oid_to_hex(&cmd->new_oid);
argv[4] = NULL;
proc.no_stdin = 1;
static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
{
static struct lock_file shallow_lock;
- struct sha1_array extra = SHA1_ARRAY_INIT;
+ struct oid_array extra = OID_ARRAY_INIT;
struct check_connected_options opt = CHECK_CONNECTED_INIT;
uint32_t mask = 1 << (cmd->index % 32);
int i;
if (si->used_shallow[i] &&
(si->used_shallow[i][cmd->index / 32] & mask) &&
!delayed_reachability_test(si, i))
- sha1_array_append(&extra, si->shallow->sha1[i]);
+ oid_array_append(&extra, &si->shallow->oid[i]);
opt.env = tmp_objdir_env(tmp_objdir);
setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra);
if (check_connected(command_singleton_iterator, cmd, &opt)) {
rollback_lock_file(&shallow_lock);
- sha1_array_clear(&extra);
+ oid_array_clear(&extra);
return -1;
}
* not lose these new roots..
*/
for (i = 0; i < extra.nr; i++)
- register_shallow(extra.sha1[i]);
+ register_shallow(extra.oid[i].hash);
si->shallow_ref[cmd->index] = 0;
- sha1_array_clear(&extra);
+ oid_array_clear(&extra);
return 0;
}
const char *name = cmd->ref_name;
struct strbuf namespaced_name_buf = STRBUF_INIT;
const char *namespaced_name, *ret;
- unsigned char *old_sha1 = cmd->old_sha1;
- unsigned char *new_sha1 = cmd->new_sha1;
+ struct object_id *old_oid = &cmd->old_oid;
+ struct object_id *new_oid = &cmd->new_oid;
/* only refs/... are allowed */
if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
refuse_unconfigured_deny();
return "branch is currently checked out";
case DENY_UPDATE_INSTEAD:
- ret = update_worktree(new_sha1);
+ ret = update_worktree(new_oid->hash);
if (ret)
return ret;
break;
}
}
- if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
+ if (!is_null_oid(new_oid) && !has_object_file(new_oid)) {
error("unpack should have generated %s, "
- "but I can't find it!", sha1_to_hex(new_sha1));
+ "but I can't find it!", oid_to_hex(new_oid));
return "bad pack";
}
- if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
+ if (!is_null_oid(old_oid) && is_null_oid(new_oid)) {
if (deny_deletes && starts_with(name, "refs/heads/")) {
rp_error("denying ref deletion for %s", name);
return "deletion prohibited";
}
}
- if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
- !is_null_sha1(old_sha1) &&
+ if (deny_non_fast_forwards && !is_null_oid(new_oid) &&
+ !is_null_oid(old_oid) &&
starts_with(name, "refs/heads/")) {
struct object *old_object, *new_object;
struct commit *old_commit, *new_commit;
- old_object = parse_object(old_sha1);
- new_object = parse_object(new_sha1);
+ old_object = parse_object(old_oid->hash);
+ new_object = parse_object(new_oid->hash);
if (!old_object || !new_object ||
old_object->type != OBJ_COMMIT ||
return "hook declined";
}
- if (is_null_sha1(new_sha1)) {
+ if (is_null_oid(new_oid)) {
struct strbuf err = STRBUF_INIT;
- if (!parse_object(old_sha1)) {
- old_sha1 = NULL;
+ if (!parse_object(old_oid->hash)) {
+ old_oid = NULL;
if (ref_exists(name)) {
rp_warning("Allowing deletion of corrupt ref.");
} else {
}
if (ref_transaction_delete(transaction,
namespaced_name,
- old_sha1,
+ old_oid->hash,
0, "push", &err)) {
rp_error("%s", err.buf);
strbuf_release(&err);
if (ref_transaction_update(transaction,
namespaced_name,
- new_sha1, old_sha1,
+ new_oid->hash, old_oid->hash,
0, "push",
&err)) {
rp_error("%s", err.buf);
const char *dst_name;
struct string_list_item *item;
struct command *dst_cmd;
- unsigned char sha1[GIT_SHA1_RAWSZ];
+ unsigned char sha1[GIT_MAX_RAWSZ];
int flag;
strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
dst_cmd = (struct command *) item->util;
- if (!hashcmp(cmd->old_sha1, dst_cmd->old_sha1) &&
- !hashcmp(cmd->new_sha1, dst_cmd->new_sha1))
+ if (!oidcmp(&cmd->old_oid, &dst_cmd->old_oid) &&
+ !oidcmp(&cmd->new_oid, &dst_cmd->new_oid))
return;
dst_cmd->skip_update = 1;
rp_error("refusing inconsistent update between symref '%s' (%s..%s) and"
" its target '%s' (%s..%s)",
cmd->ref_name,
- find_unique_abbrev(cmd->old_sha1, DEFAULT_ABBREV),
- find_unique_abbrev(cmd->new_sha1, DEFAULT_ABBREV),
+ find_unique_abbrev(cmd->old_oid.hash, DEFAULT_ABBREV),
+ find_unique_abbrev(cmd->new_oid.hash, DEFAULT_ABBREV),
dst_cmd->ref_name,
- find_unique_abbrev(dst_cmd->old_sha1, DEFAULT_ABBREV),
- find_unique_abbrev(dst_cmd->new_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(dst_cmd->old_oid.hash, DEFAULT_ABBREV),
+ find_unique_abbrev(dst_cmd->new_oid.hash, DEFAULT_ABBREV));
cmd->error_string = dst_cmd->error_string =
"inconsistent aliased update";
struct command **cmd_list = cb_data;
struct command *cmd = *cmd_list;
- if (!cmd || is_null_sha1(cmd->new_sha1))
+ if (!cmd || is_null_oid(&cmd->new_oid))
return -1; /* end of list */
*cmd_list = NULL; /* this returns only one */
- hashcpy(sha1, cmd->new_sha1);
+ hashcpy(sha1, cmd->new_oid.hash);
return 0;
}
if (shallow_update && data->si->shallow_ref[cmd->index])
/* to be checked in update_shallow_ref() */
continue;
- if (!is_null_sha1(cmd->new_sha1) && !cmd->skip_update) {
- hashcpy(sha1, cmd->new_sha1);
+ if (!is_null_oid(&cmd->new_oid) && !cmd->skip_update) {
+ hashcpy(sha1, cmd->new_oid.hash);
*cmd_list = cmd->next;
return 0;
}
if (!ref_is_hidden(cmd->ref_name, refname_full.buf))
continue;
- if (is_null_sha1(cmd->new_sha1))
+ if (is_null_oid(&cmd->new_oid))
cmd->error_string = "deny deleting a hidden ref";
else
cmd->error_string = "deny updating a hidden ref";
const char *line,
int linelen)
{
- unsigned char old_sha1[20], new_sha1[20];
+ struct object_id old_oid, new_oid;
struct command *cmd;
const char *refname;
int reflen;
+ const char *p;
- if (linelen < 83 ||
- line[40] != ' ' ||
- line[81] != ' ' ||
- get_sha1_hex(line, old_sha1) ||
- get_sha1_hex(line + 41, new_sha1))
+ if (parse_oid_hex(line, &old_oid, &p) ||
+ *p++ != ' ' ||
+ parse_oid_hex(p, &new_oid, &p) ||
+ *p++ != ' ')
die("protocol error: expected old/new/ref, got '%s'", line);
- refname = line + 82;
- reflen = linelen - 82;
+ refname = p;
+ reflen = linelen - (p - line);
FLEX_ALLOC_MEM(cmd, ref_name, refname, reflen);
- hashcpy(cmd->old_sha1, old_sha1);
- hashcpy(cmd->new_sha1, new_sha1);
+ oidcpy(&cmd->old_oid, &old_oid);
+ oidcpy(&cmd->new_oid, &new_oid);
*tail = cmd;
return &cmd->next;
}
}
}
-static struct command *read_head_info(struct sha1_array *shallow)
+static struct command *read_head_info(struct oid_array *shallow)
{
struct command *commands = NULL;
struct command **p = &commands;
if (!line)
break;
- if (len == 48 && starts_with(line, "shallow ")) {
- unsigned char sha1[20];
- if (get_sha1_hex(line + 8, sha1))
+ if (len > 8 && starts_with(line, "shallow ")) {
+ struct object_id oid;
+ if (get_oid_hex(line + 8, &oid))
die("protocol error: expected shallow sha, got '%s'",
line + 8);
- sha1_array_append(shallow, sha1);
+ oid_array_append(shallow, &oid);
continue;
}
static const char *pack_lockfile;
+static void push_header_arg(struct argv_array *args, struct pack_header *hdr)
+{
+ argv_array_pushf(args, "--pack_header=%"PRIu32",%"PRIu32,
+ ntohl(hdr->hdr_version), ntohl(hdr->hdr_entries));
+}
+
static const char *unpack(int err_fd, struct shallow_info *si)
{
struct pack_header hdr;
const char *hdr_err;
int status;
- char hdr_arg[38];
struct child_process child = CHILD_PROCESS_INIT;
int fsck_objects = (receive_fsck_objects >= 0
? receive_fsck_objects
close(err_fd);
return hdr_err;
}
- snprintf(hdr_arg, sizeof(hdr_arg),
- "--pack_header=%"PRIu32",%"PRIu32,
- ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
if (si->nr_ours || si->nr_theirs) {
alt_shallow_file = setup_temporary_shallow(si->shallow);
tmp_objdir_add_as_alternate(tmp_objdir);
if (ntohl(hdr.hdr_entries) < unpack_limit) {
- argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL);
+ argv_array_push(&child.args, "unpack-objects");
+ push_header_arg(&child.args, &hdr);
if (quiet)
argv_array_push(&child.args, "-q");
if (fsck_objects)
} else {
char hostname[256];
- argv_array_pushl(&child.args, "index-pack",
- "--stdin", hdr_arg, NULL);
+ argv_array_pushl(&child.args, "index-pack", "--stdin", NULL);
+ push_header_arg(&child.args, &hdr);
if (gethostname(hostname, sizeof(hostname)))
xsnprintf(hostname, sizeof(hostname), "localhost");
static void update_shallow_info(struct command *commands,
struct shallow_info *si,
- struct sha1_array *ref)
+ struct oid_array *ref)
{
struct command *cmd;
int *ref_status;
}
for (cmd = commands; cmd; cmd = cmd->next) {
- if (is_null_sha1(cmd->new_sha1))
+ if (is_null_oid(&cmd->new_oid))
continue;
- sha1_array_append(ref, cmd->new_sha1);
+ oid_array_append(ref, &cmd->new_oid);
cmd->index = ref->nr - 1;
}
si->ref = ref;
ALLOC_ARRAY(ref_status, ref->nr);
assign_shallow_commits_to_refs(si, NULL, ref_status);
for (cmd = commands; cmd; cmd = cmd->next) {
- if (is_null_sha1(cmd->new_sha1))
+ if (is_null_oid(&cmd->new_oid))
continue;
if (ref_status[cmd->index]) {
cmd->error_string = "shallow update not allowed";
{
struct command *cmd;
for (cmd = commands; cmd; cmd = cmd->next) {
- if (!is_null_sha1(cmd->new_sha1))
+ if (!is_null_oid(&cmd->new_oid))
return 0;
}
return 1;
{
int advertise_refs = 0;
struct command *commands;
- struct sha1_array shallow = SHA1_ARRAY_INIT;
- struct sha1_array ref = SHA1_ARRAY_INIT;
+ struct oid_array shallow = OID_ARRAY_INIT;
+ struct oid_array ref = OID_ARRAY_INIT;
struct shallow_info si;
struct option options[] = {
}
if (use_sideband)
packet_flush(1);
- sha1_array_clear(&shallow);
- sha1_array_clear(&ref);
+ oid_array_clear(&shallow);
+ oid_array_clear(&ref);
free((void *)push_cert_nonce);
return 0;
}
static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
{
const char **p, *full_hex;
- char ref[PATH_MAX];
+ struct strbuf ref = STRBUF_INIT;
+ size_t base_len;
int had_error = 0;
struct object_id oid;
+ strbuf_addstr(&ref, git_replace_ref_base);
+ base_len = ref.len;
+
for (p = argv; *p; p++) {
if (get_oid(*p, &oid)) {
error("Failed to resolve '%s' as a valid ref.", *p);
had_error = 1;
continue;
}
- full_hex = oid_to_hex(&oid);
- snprintf(ref, sizeof(ref), "%s%s", git_replace_ref_base, full_hex);
- /* read_ref() may reuse the buffer */
- full_hex = ref + strlen(git_replace_ref_base);
- if (read_ref(ref, oid.hash)) {
+
+ strbuf_setlen(&ref, base_len);
+ strbuf_addstr(&ref, oid_to_hex(&oid));
+ full_hex = ref.buf + base_len;
+
+ if (read_ref(ref.buf, oid.hash)) {
error("replace ref '%s' not found.", full_hex);
had_error = 1;
continue;
}
- if (fn(full_hex, ref, &oid))
+ if (fn(full_hex, ref.buf, &oid))
had_error = 1;
}
return had_error;
static void check_ref_valid(struct object_id *object,
struct object_id *prev,
- char *ref,
- int ref_size,
+ struct strbuf *ref,
int force)
{
- if (snprintf(ref, ref_size,
- "%s%s", git_replace_ref_base,
- oid_to_hex(object)) > ref_size - 1)
- die("replace ref name too long: %.*s...", 50, ref);
- if (check_refname_format(ref, 0))
- die("'%s' is not a valid ref name.", ref);
-
- if (read_ref(ref, prev->hash))
+ strbuf_reset(ref);
+ strbuf_addf(ref, "%s%s", git_replace_ref_base, oid_to_hex(object));
+ if (check_refname_format(ref->buf, 0))
+ die("'%s' is not a valid ref name.", ref->buf);
+
+ if (read_ref(ref->buf, prev->hash))
oidclr(prev);
else if (!force)
- die("replace ref '%s' already exists", ref);
+ die("replace ref '%s' already exists", ref->buf);
}
static int replace_object_oid(const char *object_ref,
{
struct object_id prev;
enum object_type obj_type, repl_type;
- char ref[PATH_MAX];
+ struct strbuf ref = STRBUF_INIT;
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
object_ref, typename(obj_type),
replace_ref, typename(repl_type));
- check_ref_valid(object, &prev, ref, sizeof(ref), force);
+ check_ref_valid(object, &prev, &ref, force);
transaction = ref_transaction_begin(&err);
if (!transaction ||
- ref_transaction_update(transaction, ref, repl->hash, prev.hash,
+ ref_transaction_update(transaction, ref.buf, repl->hash, prev.hash,
0, NULL, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
+ strbuf_release(&ref);
return 0;
}
char *tmpfile = git_pathdup("REPLACE_EDITOBJ");
enum object_type type;
struct object_id old, new, prev;
- char ref[PATH_MAX];
+ struct strbuf ref = STRBUF_INIT;
if (get_oid(object_ref, &old) < 0)
die("Not a valid object name: '%s'", object_ref);
if (type < 0)
die("unable to get object type for %s", oid_to_hex(&old));
- check_ref_valid(&old, &prev, ref, sizeof(ref), force);
+ check_ref_valid(&old, &prev, &ref, force);
+ strbuf_release(&ref);
export_object(&old, type, raw, tmpfile);
if (launch_editor(tmpfile, NULL, NULL) < 0)
static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
{
int cnt, flags = info->flags;
- char hex[GIT_SHA1_HEXSZ + 1] = "";
+ char hex[GIT_MAX_HEXSZ + 1] = "";
struct commit_list *tried;
struct rev_info *revs = info->revs;
return 0;
}
-static int show_abbrev(const unsigned char *sha1, void *cb_data)
+static int show_abbrev(const struct object_id *oid, void *cb_data)
{
- show_rev(NORMAL, sha1, NULL);
+ show_rev(NORMAL, oid->hash, NULL);
return 0;
}
static void show_datestring(const char *flag, const char *datestr)
{
- static char buffer[100];
+ char *buffer;
/* date handling requires both flags and revs */
if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS))
return;
- snprintf(buffer, sizeof(buffer), "%s%lu", flag, approxidate(datestr));
+ buffer = xstrfmt("%s%lu", flag, approxidate(datestr));
show(buffer);
+ free(buffer);
}
static int show_file(const char *arg, int output_prefix)
const char *dest = NULL;
int fd[2];
struct child_process *conn;
- struct sha1_array extra_have = SHA1_ARRAY_INIT;
- struct sha1_array shallow = SHA1_ARRAY_INIT;
+ struct oid_array extra_have = OID_ARRAY_INIT;
+ struct oid_array shallow = OID_ARRAY_INIT;
struct ref *remote_refs, *local_refs;
int ret;
int helper_status = 0;
static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"),
N_("git tag -d <tagname>..."),
- N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]"
+ N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]"
"\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
N_("git tag -v [--format=<format>] <tagname>..."),
NULL
const void *cb_data)
{
const char **p;
- char ref[PATH_MAX];
+ struct strbuf ref = STRBUF_INIT;
int had_error = 0;
unsigned char sha1[20];
for (p = argv; *p; p++) {
- if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p)
- >= sizeof(ref)) {
- error(_("tag name too long: %.*s..."), 50, *p);
- had_error = 1;
- continue;
- }
- if (read_ref(ref, sha1)) {
+ strbuf_reset(&ref);
+ strbuf_addf(&ref, "refs/tags/%s", *p);
+ if (read_ref(ref.buf, sha1)) {
error(_("tag '%s' not found."), *p);
had_error = 1;
continue;
}
- if (fn(*p, ref, sha1, cb_data))
+ if (fn(*p, ref.buf, sha1, cb_data))
had_error = 1;
}
+ strbuf_release(&ref);
return had_error;
}
unsigned char *prev, unsigned char *result)
{
enum object_type type;
- char header_buf[1024];
- int header_len;
+ struct strbuf header = STRBUF_INIT;
char *path = NULL;
type = sha1_object_info(object, NULL);
if (type <= OBJ_NONE)
die(_("bad object type."));
- header_len = snprintf(header_buf, sizeof(header_buf),
- "object %s\n"
- "type %s\n"
- "tag %s\n"
- "tagger %s\n\n",
- sha1_to_hex(object),
- typename(type),
- tag,
- git_committer_info(IDENT_STRICT));
-
- if (header_len > sizeof(header_buf) - 1)
- die(_("tag header too big."));
+ strbuf_addf(&header,
+ "object %s\n"
+ "type %s\n"
+ "tag %s\n"
+ "tagger %s\n\n",
+ sha1_to_hex(object),
+ typename(type),
+ tag,
+ git_committer_info(IDENT_STRICT));
if (!opt->message_given) {
int fd;
if (!opt->message_given && !buf->len)
die(_("no tag message?"));
- strbuf_insert(buf, 0, header_buf, header_len);
+ strbuf_insert(buf, 0, header.buf, header.len);
+ strbuf_release(&header);
if (build_tag_object(buf, opt->sign, result) < 0) {
if (path)
OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
OPT_CONTAINS(&filter.with_commit, N_("print only tags that contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_WITH(&filter.with_commit, N_("print only tags that contain the commit")),
+ OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_MERGED(&filter, N_("print only tags that are merged")),
OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), &parse_opt_ref_sorting),
{
OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
- N_("print only tags of the object"), 0, parse_opt_object_name
+ N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
+ parse_opt_object_name, (intptr_t) "HEAD"
},
OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
}
create_tag_object = (opt.sign || annotate || msg.given || msgfile);
- if (argc == 0 && !cmdmode)
- cmdmode = 'l';
+ if (!cmdmode) {
+ if (argc == 0)
+ cmdmode = 'l';
+ else if (filter.with_commit || filter.no_commit ||
+ filter.points_at.nr || filter.merge_commit ||
+ filter.lines != -1)
+ cmdmode = 'l';
+ }
if ((create_tag_object || force) && (cmdmode != 0))
usage_with_options(git_tag_usage, options);
return ret;
}
if (filter.lines != -1)
- die(_("-n option is only allowed with -l."));
+ die(_("-n option is only allowed in list mode"));
if (filter.with_commit)
- die(_("--contains option is only allowed with -l."));
+ die(_("--contains option is only allowed in list mode"));
+ if (filter.no_commit)
+ die(_("--no-contains option is only allowed in list mode"));
if (filter.points_at.nr)
- die(_("--points-at option is only allowed with -l."));
+ die(_("--points-at option is only allowed in list mode"));
if (filter.merge_commit)
- die(_("--merged and --no-merged option are only allowed with -l"));
+ die(_("--merged and --no-merged options are only allowed in list mode"));
if (cmdmode == 'd')
return for_each_tag_name(argv, delete_tag, NULL);
if (cmdmode == 'v') {
struct stat st;
struct stat_data base;
int fd, ret = 0;
+ char *cwd;
strbuf_addstr(&mtime_dir, "mtime-test-XXXXXX");
if (!mkdtemp(mtime_dir.buf))
die_errno("Could not make temporary directory");
- fprintf(stderr, _("Testing mtime in '%s' "), xgetcwd());
+ cwd = xgetcwd();
+ fprintf(stderr, _("Testing mtime in '%s' "), cwd);
+ free(cwd);
+
atexit(remove_test_directory);
xstat_mtime_dir(&st);
fill_stat_data(&base, &st);
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
+/* The length in byte and in hex digits of the largest possible hash value. */
+#define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
+#define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
+
struct object_id {
- unsigned char hash[GIT_SHA1_RAWSZ];
+ unsigned char hash[GIT_MAX_RAWSZ];
};
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
extern const char *find_unique_abbrev(const unsigned char *sha1, int len);
extern int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len);
-extern const unsigned char null_sha1[GIT_SHA1_RAWSZ];
+extern const unsigned char null_sha1[GIT_MAX_RAWSZ];
extern const struct object_id null_oid;
static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
extern int get_oid(const char *str, struct object_id *oid);
-typedef int each_abbrev_fn(const unsigned char *sha1, void *);
+typedef int each_abbrev_fn(const struct object_id *oid, void *);
extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
extern int set_disambiguate_hint_config(const char *var, const char *value);
extern void pack_report(void);
/*
- * Create a temporary file rooted in the object database directory.
+ * Create a temporary file rooted in the object database directory, or
+ * die on failure. The filename is taken from "pattern", which should have the
+ * usual "XXXXXX" trailer, and the resulting filename is written into the
+ * "template" buffer. Returns the open descriptor.
*/
-extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
+extern int odb_mkstemp(struct strbuf *template, const char *pattern);
/*
* Generate the filename to be used for a pack file with checksum "sha1" and
--- /dev/null
+#!/usr/bin/env bash
+#
+# Script to trigger the a Git for Windows build and test run.
+# Set the $GFW_CI_TOKEN as environment variable.
+# Pass the branch (only branches on https://github.com/git/git are
+# supported) and a commit hash.
+#
+
+test $# -ne 2 && echo "Unexpected number of parameters" && exit 1
+test -z "$GFW_CI_TOKEN" && echo "GFW_CI_TOKEN not defined" && exit
+
+BRANCH=$1
+COMMIT=$2
+
+gfwci () {
+ local CURL_ERROR_CODE HTTP_CODE
+ exec 3>&1
+ HTTP_CODE=$(curl \
+ -H "Authentication: Bearer $GFW_CI_TOKEN" \
+ --silent --retry 5 --write-out '%{HTTP_CODE}' \
+ --output >(sed "$(printf '1s/^\xef\xbb\xbf//')" >cat >&3) \
+ "https://git-for-windows-ci.azurewebsites.net/api/TestNow?$1" \
+ )
+ CURL_ERROR_CODE=$?
+ if test $CURL_ERROR_CODE -ne 0
+ then
+ return $CURL_ERROR_CODE
+ fi
+ if test "$HTTP_CODE" -ge 400 && test "$HTTP_CODE" -lt 600
+ then
+ return 127
+ fi
+}
+
+# Trigger build job
+BUILD_ID=$(gfwci "action=trigger&branch=$BRANCH&commit=$COMMIT&skipTests=false")
+if test $? -ne 0
+then
+ echo "Unable to trigger Visual Studio Team Services Build"
+ echo "$BUILD_ID"
+ exit 1
+fi
+
+# Check if the $BUILD_ID contains a number
+case $BUILD_ID in
+''|*[!0-9]*) echo "Unexpected build number: $BUILD_ID" && exit 1
+esac
+
+echo "Visual Studio Team Services Build #${BUILD_ID}"
+
+# Wait until build job finished
+STATUS=
+RESULT=
+while true
+do
+ LAST_STATUS=$STATUS
+ STATUS=$(gfwci "action=status&buildId=$BUILD_ID")
+ test "$STATUS" = "$LAST_STATUS" || printf "\nStatus: $STATUS "
+ printf "."
+
+ case "$STATUS" in
+ inProgress|postponed|notStarted) sleep 10 ;; # continue
+ "completed: succeeded") RESULT="success"; break;; # success
+ *) echo "Unhandled status: $STATUS"; break;; # failure
+ esac
+done
+
+# Print log
+echo ""
+echo ""
+gfwci "action=log&buildId=$BUILD_ID" | cut -c 30-
+
+# Set exit code for TravisCI
+test "$RESULT" = "success"
enum object_type type;
if (S_ISGITLINK(mode)) {
- blob = xmalloc(100);
- *size = snprintf(blob, 100,
- "Subproject commit %s\n", oid_to_hex(oid));
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "Subproject commit %s\n", oid_to_hex(oid));
+ *size = buf.len;
+ blob = strbuf_detach(&buf, NULL);
} else if (is_null_oid(oid)) {
/* deleted blob */
*size = 0;
/* find set of paths that every parent touches */
static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
- const struct sha1_array *parents, struct diff_options *opt)
+ const struct oid_array *parents, struct diff_options *opt)
{
struct combine_diff_path *paths = NULL;
int i, num_parent = parents->nr;
opt->output_format = stat_opt;
else
opt->output_format = DIFF_FORMAT_NO_OUTPUT;
- diff_tree_sha1(parents->sha1[i], sha1, "", opt);
+ diff_tree_sha1(parents->oid[i].hash, sha1, "", opt);
diffcore_std(opt);
paths = intersect_paths(paths, i, num_parent);
* rename/copy detection, etc, comparing all trees simultaneously (= faster).
*/
static struct combine_diff_path *find_paths_multitree(
- const unsigned char *sha1, const struct sha1_array *parents,
+ const unsigned char *sha1, const struct oid_array *parents,
struct diff_options *opt)
{
int i, nparent = parents->nr;
ALLOC_ARRAY(parents_sha1, nparent);
for (i = 0; i < nparent; i++)
- parents_sha1[i] = parents->sha1[i];
+ parents_sha1[i] = parents->oid[i].hash;
/* fake list head, so worker can assume it is non-NULL */
paths_head.next = NULL;
void diff_tree_combined(const unsigned char *sha1,
- const struct sha1_array *parents,
+ const struct oid_array *parents,
int dense,
struct rev_info *rev)
{
if (stat_opt) {
diffopts.output_format = stat_opt;
- diff_tree_sha1(parents->sha1[0], sha1, "", &diffopts);
+ diff_tree_sha1(parents->oid[0].hash, sha1, "", &diffopts);
diffcore_std(&diffopts);
if (opt->orderfile)
diffcore_order(opt->orderfile);
struct rev_info *rev)
{
struct commit_list *parent = get_saved_parents(rev, commit);
- struct sha1_array parents = SHA1_ARRAY_INIT;
+ struct oid_array parents = OID_ARRAY_INIT;
while (parent) {
- sha1_array_append(&parents, parent->item->object.oid.hash);
+ oid_array_append(&parents, &parent->item->object.oid);
parent = parent->next;
}
diff_tree_combined(commit->object.oid.hash, &parents, dense, rev);
- sha1_array_clear(&parents);
+ oid_array_clear(&parents);
}
/* largest positive number a signed 32-bit integer can contain */
#define INFINITE_DEPTH 0x7fffffff
-struct sha1_array;
+struct oid_array;
struct ref;
extern int register_shallow(const unsigned char *sha1);
extern int unregister_shallow(const unsigned char *sha1);
int ac, const char **av, int shallow_flag, int not_shallow_flag);
extern void set_alternate_shallow_file(const char *path, int override);
extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
- const struct sha1_array *extra);
+ const struct oid_array *extra);
extern void setup_alternate_shallow(struct lock_file *shallow_lock,
const char **alternate_shallow_file,
- const struct sha1_array *extra);
-extern const char *setup_temporary_shallow(const struct sha1_array *extra);
+ const struct oid_array *extra);
+extern const char *setup_temporary_shallow(const struct oid_array *extra);
extern void advertise_shallow_grafts(int);
struct shallow_info {
- struct sha1_array *shallow;
+ struct oid_array *shallow;
int *ours, nr_ours;
int *theirs, nr_theirs;
- struct sha1_array *ref;
+ struct oid_array *ref;
/* for receive-pack */
uint32_t **used_shallow;
int nr_commits;
};
-extern void prepare_shallow_info(struct shallow_info *, struct sha1_array *);
+extern void prepare_shallow_info(struct shallow_info *, struct oid_array *);
extern void clear_shallow_info(struct shallow_info *);
extern void remove_nonexistent_theirs_shallow(struct shallow_info *);
extern void assign_shallow_commits_to_refs(struct shallow_info *info,
*/
struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
struct ref **list, unsigned int flags,
- struct sha1_array *extra_have,
- struct sha1_array *shallow_points)
+ struct oid_array *extra_have,
+ struct oid_array *shallow_points)
{
struct ref **orig_list = list;
die("protocol error: expected shallow sha-1, got '%s'", arg);
if (!shallow_points)
die("repository on the other end cannot be shallow");
- sha1_array_append(shallow_points, old_oid.hash);
+ oid_array_append(shallow_points, &old_oid);
continue;
}
}
if (extra_have && !strcmp(name, ".have")) {
- sha1_array_append(extra_have, old_oid.hash);
+ oid_array_append(extra_have, &old_oid);
continue;
}
--*)
__gitcomp "
--color --no-color --verbose --abbrev= --no-abbrev
- --track --no-track --contains --merged --no-merged
+ --track --no-track --contains --no-contains --merged --no-merged
--set-upstream-to= --edit-description --list
--unset-upstream --delete --move --remotes
--column --no-column --sort= --points-at
__gitcomp "
--list --delete --verify --annotate --message --file
--sign --cleanup --local-user --force --column --sort=
- --contains --points-at --merged --no-merged --create-reflog
+ --contains --no-contains --points-at --merged --no-merged --create-reflog
"
;;
esac
. git-sh-setup
search_reflog () {
- sed -ne 's~^\([^ ]*\) .*\tcheckout: moving from '"$1"' .*~\1~p' \
+ sed -ne 's~^\([^ ]*\) .* checkout: moving from '"$1"' .*~\1~p' \
< "$GIT_DIR"/logs/HEAD
}
search_reflog_merges () {
git rev-parse $(
- sed -ne 's~^[^ ]* \([^ ]*\) .*\tmerge '"$1"':.*~\1^2~p' \
+ sed -ne 's~^[^ ]* \([^ ]*\) .* merge '"$1"':.*~\1^2~p' \
< "$GIT_DIR"/logs/HEAD
)
}
fclose(fp);
}
-static int run_service_command(const char **argv)
+static int run_service_command(struct child_process *cld)
{
- struct child_process cld = CHILD_PROCESS_INIT;
-
- cld.argv = argv;
- cld.git_cmd = 1;
- cld.err = -1;
- if (start_command(&cld))
+ argv_array_push(&cld->args, ".");
+ cld->git_cmd = 1;
+ cld->err = -1;
+ if (start_command(cld))
return -1;
close(0);
close(1);
- copy_to_log(cld.err);
+ copy_to_log(cld->err);
- return finish_command(&cld);
+ return finish_command(cld);
}
static int upload_pack(void)
{
- /* Timeout as string */
- char timeout_buf[64];
- const char *argv[] = { "upload-pack", "--strict", NULL, ".", NULL };
-
- argv[2] = timeout_buf;
-
- snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
- return run_service_command(argv);
+ struct child_process cld = CHILD_PROCESS_INIT;
+ argv_array_pushl(&cld.args, "upload-pack", "--strict", NULL);
+ argv_array_pushf(&cld.args, "--timeout=%u", timeout);
+ return run_service_command(&cld);
}
static int upload_archive(void)
{
- static const char *argv[] = { "upload-archive", ".", NULL };
- return run_service_command(argv);
+ struct child_process cld = CHILD_PROCESS_INIT;
+ argv_array_push(&cld.args, "upload-archive");
+ return run_service_command(&cld);
}
static int receive_pack(void)
{
- static const char *argv[] = { "receive-pack", ".", NULL };
- return run_service_command(argv);
+ struct child_process cld = CHILD_PROCESS_INIT;
+ argv_array_push(&cld.args, "receive-pack");
+ return run_service_command(&cld);
}
static struct daemon_service daemon_service[] = {
*/
const char *name;
- char hex[GIT_SHA1_HEXSZ + 1];
+ char hex[GIT_MAX_HEXSZ + 1];
char mode[10];
/*
* uniqueness across all objects (statistically speaking).
*/
if (abblen < GIT_SHA1_HEXSZ - 3) {
- static char hex[GIT_SHA1_HEXSZ + 1];
+ static char hex[GIT_MAX_HEXSZ + 1];
if (len < abblen && abblen <= len + 2)
xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, "..");
else
data->patchlen += new_len;
}
+static void patch_id_add_string(git_SHA_CTX *ctx, const char *str)
+{
+ git_SHA1_Update(ctx, str, strlen(str));
+}
+
+static void patch_id_add_mode(git_SHA_CTX *ctx, unsigned mode)
+{
+ /* large enough for 2^32 in octal */
+ char buf[12];
+ int len = xsnprintf(buf, sizeof(buf), "%06o", mode);
+ git_SHA1_Update(ctx, buf, len);
+}
+
/* returns 0 upon success, and writes result into sha1 */
static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
{
int i;
git_SHA_CTX ctx;
struct patch_id_t data;
- char buffer[PATH_MAX * 4 + 20];
git_SHA1_Init(&ctx);
memset(&data, 0, sizeof(struct patch_id_t));
len1 = remove_space(p->one->path, strlen(p->one->path));
len2 = remove_space(p->two->path, strlen(p->two->path));
- if (p->one->mode == 0)
- len1 = snprintf(buffer, sizeof(buffer),
- "diff--gita/%.*sb/%.*s"
- "newfilemode%06o"
- "---/dev/null"
- "+++b/%.*s",
- len1, p->one->path,
- len2, p->two->path,
- p->two->mode,
- len2, p->two->path);
- else if (p->two->mode == 0)
- len1 = snprintf(buffer, sizeof(buffer),
- "diff--gita/%.*sb/%.*s"
- "deletedfilemode%06o"
- "---a/%.*s"
- "+++/dev/null",
- len1, p->one->path,
- len2, p->two->path,
- p->one->mode,
- len1, p->one->path);
- else
- len1 = snprintf(buffer, sizeof(buffer),
- "diff--gita/%.*sb/%.*s"
- "---a/%.*s"
- "+++b/%.*s",
- len1, p->one->path,
- len2, p->two->path,
- len1, p->one->path,
- len2, p->two->path);
- git_SHA1_Update(&ctx, buffer, len1);
+ patch_id_add_string(&ctx, "diff--git");
+ patch_id_add_string(&ctx, "a/");
+ git_SHA1_Update(&ctx, p->one->path, len1);
+ patch_id_add_string(&ctx, "b/");
+ git_SHA1_Update(&ctx, p->two->path, len2);
+
+ if (p->one->mode == 0) {
+ patch_id_add_string(&ctx, "newfilemode");
+ patch_id_add_mode(&ctx, p->two->mode);
+ patch_id_add_string(&ctx, "---/dev/null");
+ patch_id_add_string(&ctx, "+++b/");
+ git_SHA1_Update(&ctx, p->two->path, len2);
+ } else if (p->two->mode == 0) {
+ patch_id_add_string(&ctx, "deletedfilemode");
+ patch_id_add_mode(&ctx, p->one->mode);
+ patch_id_add_string(&ctx, "---a/");
+ git_SHA1_Update(&ctx, p->one->path, len1);
+ patch_id_add_string(&ctx, "+++/dev/null");
+ } else {
+ patch_id_add_string(&ctx, "---a/");
+ git_SHA1_Update(&ctx, p->one->path, len1);
+ patch_id_add_string(&ctx, "+++b/");
+ git_SHA1_Update(&ctx, p->two->path, len2);
+ }
if (diff_header_only)
continue;
struct strbuf;
struct diff_filespec;
struct userdiff_driver;
-struct sha1_array;
+struct oid_array;
struct commit;
struct combine_diff_path;
extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
int dense, struct rev_info *);
-extern void diff_tree_combined(const unsigned char *sha1, const struct sha1_array *parents, int dense, struct rev_info *rev);
+extern void diff_tree_combined(const unsigned char *sha1, const struct oid_array *parents, int dense, struct rev_info *rev);
extern void diff_tree_combined_merge(const struct commit *commit, int dense, struct rev_info *rev);
return git_object_dir;
}
-int odb_mkstemp(char *template, size_t limit, const char *pattern)
+int odb_mkstemp(struct strbuf *template, const char *pattern)
{
int fd;
/*
* restrictive except to remove write permission.
*/
int mode = 0444;
- snprintf(template, limit, "%s/%s",
- get_object_directory(), pattern);
- fd = git_mkstemp_mode(template, mode);
+ git_path_buf(template, "objects/%s", pattern);
+ fd = git_mkstemp_mode(template->buf, mode);
if (0 <= fd)
return fd;
/* slow path */
/* some mkstemp implementations erase template on failure */
- snprintf(template, limit, "%s/%s",
- get_object_directory(), pattern);
- safe_create_leading_directories(template);
- return xmkstemp_mode(template, mode);
+ git_path_buf(template, "objects/%s", pattern);
+ safe_create_leading_directories(template->buf);
+ return xmkstemp_mode(template->buf, mode);
}
int odb_pack_keep(const char *name)
static void start_packfile(void)
{
- static char tmp_file[PATH_MAX];
+ struct strbuf tmp_file = STRBUF_INIT;
struct packed_git *p;
struct pack_header hdr;
int pack_fd;
- pack_fd = odb_mkstemp(tmp_file, sizeof(tmp_file),
- "pack/tmp_pack_XXXXXX");
- FLEX_ALLOC_STR(p, pack_name, tmp_file);
+ pack_fd = odb_mkstemp(&tmp_file, "pack/tmp_pack_XXXXXX");
+ FLEX_ALLOC_STR(p, pack_name, tmp_file.buf);
+ strbuf_release(&tmp_file);
+
p->pack_fd = pack_fd;
p->do_not_close = 1;
pack_file = sha1fd(pack_fd, p->pack_name);
struct ref **sought, int nr_sought,
struct shallow_info *si)
{
- struct sha1_array ref = SHA1_ARRAY_INIT;
+ struct oid_array ref = OID_ARRAY_INIT;
int *status;
int i;
* shallow points that exist in the pack (iow in repo
* after get_pack() and reprepare_packed_git())
*/
- struct sha1_array extra = SHA1_ARRAY_INIT;
- unsigned char (*sha1)[20] = si->shallow->sha1;
+ struct oid_array extra = OID_ARRAY_INIT;
+ struct object_id *oid = si->shallow->oid;
for (i = 0; i < si->shallow->nr; i++)
- if (has_sha1_file(sha1[i]))
- sha1_array_append(&extra, sha1[i]);
+ if (has_object_file(&oid[i]))
+ oid_array_append(&extra, &oid[i]);
if (extra.nr) {
setup_alternate_shallow(&shallow_lock,
&alternate_shallow_file,
&extra);
commit_lock_file(&shallow_lock);
}
- sha1_array_clear(&extra);
+ oid_array_clear(&extra);
return;
}
if (!si->nr_ours && !si->nr_theirs)
return;
for (i = 0; i < nr_sought; i++)
- sha1_array_append(&ref, sought[i]->old_oid.hash);
+ oid_array_append(&ref, &sought[i]->old_oid);
si->ref = &ref;
if (args->update_shallow) {
* shallow roots that are actually reachable from new
* refs.
*/
- struct sha1_array extra = SHA1_ARRAY_INIT;
- unsigned char (*sha1)[20] = si->shallow->sha1;
+ struct oid_array extra = OID_ARRAY_INIT;
+ struct object_id *oid = si->shallow->oid;
assign_shallow_commits_to_refs(si, NULL, NULL);
if (!si->nr_ours && !si->nr_theirs) {
- sha1_array_clear(&ref);
+ oid_array_clear(&ref);
return;
}
for (i = 0; i < si->nr_ours; i++)
- sha1_array_append(&extra, sha1[si->ours[i]]);
+ oid_array_append(&extra, &oid[si->ours[i]]);
for (i = 0; i < si->nr_theirs; i++)
- sha1_array_append(&extra, sha1[si->theirs[i]]);
+ oid_array_append(&extra, &oid[si->theirs[i]]);
setup_alternate_shallow(&shallow_lock,
&alternate_shallow_file,
&extra);
commit_lock_file(&shallow_lock);
- sha1_array_clear(&extra);
- sha1_array_clear(&ref);
+ oid_array_clear(&extra);
+ oid_array_clear(&ref);
return;
}
sought[i]->status = REF_STATUS_REJECT_SHALLOW;
}
free(status);
- sha1_array_clear(&ref);
+ oid_array_clear(&ref);
}
struct ref *fetch_pack(struct fetch_pack_args *args,
const struct ref *ref,
const char *dest,
struct ref **sought, int nr_sought,
- struct sha1_array *shallow,
+ struct oid_array *shallow,
char **pack_lockfile)
{
struct ref *ref_cpy;
#include "string-list.h"
#include "run-command.h"
-struct sha1_array;
+struct oid_array;
struct fetch_pack_args {
const char *uploadpack;
const char *dest,
struct ref **sought,
int nr_sought,
- struct sha1_array *shallow,
+ struct oid_array *shallow,
char **pack_lockfile);
/*
static void init_skiplist(struct fsck_options *options, const char *path)
{
- static struct sha1_array skiplist = SHA1_ARRAY_INIT;
+ static struct oid_array skiplist = OID_ARRAY_INIT;
int sorted, fd;
- char buffer[41];
- unsigned char sha1[20];
+ char buffer[GIT_MAX_HEXSZ + 1];
+ struct object_id oid;
if (options->skiplist)
sorted = options->skiplist->sorted;
if (fd < 0)
die("Could not open skip list: %s", path);
for (;;) {
+ const char *p;
int result = read_in_full(fd, buffer, sizeof(buffer));
if (result < 0)
die_errno("Could not read '%s'", path);
if (!result)
break;
- if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n')
+ if (parse_oid_hex(buffer, &oid, &p) || *p != '\n')
die("Invalid SHA-1: %s", buffer);
- sha1_array_append(&skiplist, sha1);
+ oid_array_append(&skiplist, &oid);
if (sorted && skiplist.nr > 1 &&
- hashcmp(skiplist.sha1[skiplist.nr - 2],
- sha1) > 0)
+ oidcmp(&skiplist.oid[skiplist.nr - 2],
+ &oid) > 0)
sorted = 0;
}
close(fd);
return 0;
if (options->skiplist && object &&
- sha1_array_lookup(options->skiplist, object->oid.hash) >= 0)
+ oid_array_lookup(options->skiplist, &object->oid) >= 0)
return 0;
if (msg_type == FSCK_FATAL)
fsck_error error_func;
unsigned strict:1;
int *msg_type;
- struct sha1_array *skiplist;
+ struct oid_array *skiplist;
struct decoration *object_names;
};
}
if (opt->linenum) {
char buf[32];
- snprintf(buf, sizeof(buf), "%d", lno);
+ xsnprintf(buf, sizeof(buf), "%d", lno);
output_color(opt, buf, strlen(buf), opt->color_lineno);
output_sep(opt, sign);
}
opt->color_filename);
output_sep(opt, ':');
}
- snprintf(buf, sizeof(buf), "%u\n", count);
+ xsnprintf(buf, sizeof(buf), "%u\n", count);
opt->output(opt, buf, strlen(buf));
return 1;
}
char *sha1_to_hex(const unsigned char *sha1)
{
static int bufno;
- static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
+ static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
return sha1_to_hex_r(hexbuffer[bufno], sha1);
}
* FAILONERROR it is lost, so we can give only the numeric
* status code.
*/
- snprintf(curl_errorstr, sizeof(curl_errorstr),
- "The requested URL returned error: %ld",
- results->http_code);
+ xsnprintf(curl_errorstr, sizeof(curl_errorstr),
+ "The requested URL returned error: %ld",
+ results->http_code);
}
if (results->curl_result == CURLE_OK) {
{
slot->results = results;
if (!start_active_slot(slot)) {
- snprintf(curl_errorstr, sizeof(curl_errorstr),
- "failed to start HTTP request");
+ xsnprintf(curl_errorstr, sizeof(curl_errorstr),
+ "failed to start HTTP request");
return HTTP_START_FAILED;
}
int gai;
char portstr[6];
- snprintf(portstr, sizeof(portstr), "%d", srvc->port);
+ xsnprintf(portstr, sizeof(portstr), "%d", srvc->port);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
const char *filename,
uint16_t options)
{
- static char tmp_file[PATH_MAX];
static uint16_t default_version = 1;
static uint16_t flags = BITMAP_OPT_FULL_DAG;
+ struct strbuf tmp_file = STRBUF_INIT;
struct sha1file *f;
struct bitmap_disk_header header;
- int fd = odb_mkstemp(tmp_file, sizeof(tmp_file), "pack/tmp_bitmap_XXXXXX");
+ int fd = odb_mkstemp(&tmp_file, "pack/tmp_bitmap_XXXXXX");
- if (fd < 0)
- die_errno("unable to create '%s'", tmp_file);
- f = sha1fd(fd, tmp_file);
+ f = sha1fd(fd, tmp_file.buf);
memcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));
header.version = htons(default_version);
sha1close(f, NULL, CSUM_FSYNC);
- if (adjust_shared_perm(tmp_file))
+ if (adjust_shared_perm(tmp_file.buf))
die_errno("unable to make temporary bitmap file readable");
- if (rename(tmp_file, filename))
+ if (rename(tmp_file.buf, filename))
die_errno("unable to rename temporary bitmap file to '%s'", filename);
+
+ strbuf_release(&tmp_file);
}
f = sha1fd_check(index_name);
} else {
if (!index_name) {
- static char tmp_file[PATH_MAX];
- fd = odb_mkstemp(tmp_file, sizeof(tmp_file), "pack/tmp_idx_XXXXXX");
- index_name = xstrdup(tmp_file);
+ struct strbuf tmp_file = STRBUF_INIT;
+ fd = odb_mkstemp(&tmp_file, "pack/tmp_idx_XXXXXX");
+ index_name = strbuf_detach(&tmp_file, NULL);
} else {
unlink(index_name);
fd = open(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ if (fd < 0)
+ die_errno("unable to create '%s'", index_name);
}
- if (fd < 0)
- die_errno("unable to create '%s'", index_name);
f = sha1fd(fd, index_name);
}
struct sha1file *create_tmp_packfile(char **pack_tmp_name)
{
- char tmpname[PATH_MAX];
+ struct strbuf tmpname = STRBUF_INIT;
int fd;
- fd = odb_mkstemp(tmpname, sizeof(tmpname), "pack/tmp_pack_XXXXXX");
- *pack_tmp_name = xstrdup(tmpname);
+ fd = odb_mkstemp(&tmpname, "pack/tmp_pack_XXXXXX");
+ *pack_tmp_name = strbuf_detach(&tmpname, NULL);
return sha1fd(fd, *pack_tmp_name);
}
int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
{
- unsigned char sha1[20];
+ struct object_id oid;
if (unset) {
- sha1_array_clear(opt->value);
+ oid_array_clear(opt->value);
return 0;
}
if (!arg)
return -1;
- if (get_sha1(arg, sha1))
+ if (get_oid(arg, &oid))
return error(_("malformed object name '%s'"), arg);
- sha1_array_append(opt->value, sha1);
+ oid_array_append(opt->value, &oid);
return 0;
}
PARSE_OPT_LASTARG_DEFAULT | flag, \
parse_opt_commits, (intptr_t) "HEAD" \
}
-#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0)
-#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN)
+#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, PARSE_OPT_NONEG)
+#define OPT_NO_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)
+#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
+#define OPT_WITHOUT(v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
#endif
struct commit *commit,
struct patch_ids *ids)
{
- unsigned char header_only_patch_id[GIT_SHA1_RAWSZ];
+ unsigned char header_only_patch_id[GIT_MAX_RAWSZ];
patch->commit = commit;
if (commit_patch_id(commit, &ids->diffopts, header_only_patch_id, 1))
struct patch_id {
struct hashmap_entry ent;
- unsigned char patch_id[GIT_SHA1_RAWSZ];
+ unsigned char patch_id[GIT_MAX_RAWSZ];
struct commit *commit;
};
struct ref_array *array;
struct ref_filter *filter;
struct contains_cache contains_cache;
+ struct contains_cache no_contains_cache;
};
/*
}
static int commit_contains(struct ref_filter *filter, struct commit *commit,
- struct contains_cache *cache)
+ struct commit_list *list, struct contains_cache *cache)
{
if (filter->with_commit_tag_algo)
- return contains_tag_algo(commit, filter->with_commit, cache) == CONTAINS_YES;
- return is_descendant_of(commit, filter->with_commit);
+ return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
+ return is_descendant_of(commit, list);
}
/*
* the need to parse the object via parse_object(). peel_ref() might be a
* more efficient alternative to obtain the pointee.
*/
-static const unsigned char *match_points_at(struct sha1_array *points_at,
- const unsigned char *sha1,
- const char *refname)
+static const struct object_id *match_points_at(struct oid_array *points_at,
+ const struct object_id *oid,
+ const char *refname)
{
- const unsigned char *tagged_sha1 = NULL;
+ const struct object_id *tagged_oid = NULL;
struct object *obj;
- if (sha1_array_lookup(points_at, sha1) >= 0)
- return sha1;
- obj = parse_object(sha1);
+ if (oid_array_lookup(points_at, oid) >= 0)
+ return oid;
+ obj = parse_object(oid->hash);
if (!obj)
die(_("malformed object at '%s'"), refname);
if (obj->type == OBJ_TAG)
- tagged_sha1 = ((struct tag *)obj)->tagged->oid.hash;
- if (tagged_sha1 && sha1_array_lookup(points_at, tagged_sha1) >= 0)
- return tagged_sha1;
+ tagged_oid = &((struct tag *)obj)->tagged->oid;
+ if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0)
+ return tagged_oid;
return NULL;
}
if (!filter_pattern_match(filter, refname))
return 0;
- if (filter->points_at.nr && !match_points_at(&filter->points_at, oid->hash, refname))
+ if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
return 0;
/*
* obtain the commit using the 'oid' available and discard all
* non-commits early. The actual filtering is done later.
*/
- if (filter->merge_commit || filter->with_commit || filter->verbose) {
+ if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) {
commit = lookup_commit_reference_gently(oid->hash, 1);
if (!commit)
return 0;
- /* We perform the filtering for the '--contains' option */
+ /* We perform the filtering for the '--contains' option... */
if (filter->with_commit &&
- !commit_contains(filter, commit, &ref_cbdata->contains_cache))
+ !commit_contains(filter, commit, filter->with_commit, &ref_cbdata->contains_cache))
+ return 0;
+ /* ...or for the `--no-contains' option */
+ if (filter->no_commit &&
+ commit_contains(filter, commit, filter->no_commit, &ref_cbdata->no_contains_cache))
return 0;
}
filter->kind = type & FILTER_REFS_KIND_MASK;
init_contains_cache(&ref_cbdata.contains_cache);
+ init_contains_cache(&ref_cbdata.no_contains_cache);
/* Simple per-ref filtering */
if (!filter->kind)
}
clear_contains_cache(&ref_cbdata.contains_cache);
+ clear_contains_cache(&ref_cbdata.no_contains_cache);
/* Filters that need revision walking */
if (filter->merge_commit)
{
struct ref_filter *rf = opt->value;
unsigned char sha1[20];
+ int no_merged = starts_with(opt->long_name, "no");
+
+ if (rf->merge) {
+ if (no_merged) {
+ return opterror(opt, "is incompatible with --merged", 0);
+ } else {
+ return opterror(opt, "is incompatible with --no-merged", 0);
+ }
+ }
- rf->merge = starts_with(opt->long_name, "no")
+ rf->merge = no_merged
? REF_FILTER_MERGED_OMIT
: REF_FILTER_MERGED_INCLUDE;
struct ref_filter {
const char **name_patterns;
- struct sha1_array points_at;
+ struct oid_array points_at;
struct commit_list *with_commit;
+ struct commit_list *no_commit;
enum {
REF_FILTER_MERGED_NONE = 0,
{
const char **p, *r;
int refs_found = 0;
+ struct strbuf fullref = STRBUF_INIT;
*ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
- char fullref[PATH_MAX];
unsigned char sha1_from_ref[20];
unsigned char *this_result;
int flag;
this_result = refs_found ? sha1_from_ref : sha1;
- mksnpath(fullref, sizeof(fullref), *p, len, str);
- r = resolve_ref_unsafe(fullref, RESOLVE_REF_READING,
+ strbuf_reset(&fullref);
+ strbuf_addf(&fullref, *p, len, str);
+ r = resolve_ref_unsafe(fullref.buf, RESOLVE_REF_READING,
this_result, &flag);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
if (!warn_ambiguous_refs)
break;
- } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
- warning("ignoring dangling symref %s.", fullref);
- } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
- warning("ignoring broken ref %s.", fullref);
+ } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
+ warning("ignoring dangling symref %s.", fullref.buf);
+ } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
+ warning("ignoring broken ref %s.", fullref.buf);
}
}
+ strbuf_release(&fullref);
return refs_found;
}
char *last_branch = substitute_branch_name(&str, &len);
const char **p;
int logs_found = 0;
+ struct strbuf path = STRBUF_INIT;
*log = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
unsigned char hash[20];
- char path[PATH_MAX];
const char *ref, *it;
- mksnpath(path, sizeof(path), *p, len, str);
- ref = resolve_ref_unsafe(path, RESOLVE_REF_READING,
+ strbuf_reset(&path);
+ strbuf_addf(&path, *p, len, str);
+ ref = resolve_ref_unsafe(path.buf, RESOLVE_REF_READING,
hash, NULL);
if (!ref)
continue;
- if (reflog_exists(path))
- it = path;
- else if (strcmp(ref, path) && reflog_exists(ref))
+ if (reflog_exists(path.buf))
+ it = path.buf;
+ else if (strcmp(ref, path.buf) && reflog_exists(ref))
it = ref;
else
continue;
if (!warn_ambiguous_refs)
break;
}
+ strbuf_release(&path);
free(last_branch);
return logs_found;
}
static char **scanf_fmts;
static int nr_rules;
char *short_name;
+ struct strbuf resolved_buf = STRBUF_INIT;
if (!nr_rules) {
/*
*/
for (j = 0; j < rules_to_fail; j++) {
const char *rule = ref_rev_parse_rules[j];
- char refname[PATH_MAX];
/* skip matched rule */
if (i == j)
* (with this previous rule) to a valid ref
* read_ref() returns 0 on success
*/
- mksnpath(refname, sizeof(refname),
- rule, short_name_len, short_name);
- if (ref_exists(refname))
+ strbuf_reset(&resolved_buf);
+ strbuf_addf(&resolved_buf, rule,
+ short_name_len, short_name);
+ if (ref_exists(resolved_buf.buf))
break;
}
* short name is non-ambiguous if all previous rules
* haven't resolved to a valid ref
*/
- if (j == rules_to_fail)
+ if (j == rules_to_fail) {
+ strbuf_release(&resolved_buf);
return short_name;
+ }
}
+ strbuf_release(&resolved_buf);
free(short_name);
return xstrdup(refname);
}
char *buf;
size_t len;
struct ref *refs;
- struct sha1_array shallow;
+ struct oid_array shallow;
unsigned proto_git : 1;
};
static struct discovery *last_discovery;
if (d) {
if (d == last_discovery)
last_discovery = NULL;
- free(d->shallow.sha1);
+ free(d->shallow.oid);
free(d->buf_alloc);
free_refs(d->refs);
free(d);
return entry;
}
-int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unset)
+static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unset)
{
const char *colon;
struct push_cas *entry;
*/
void free_refs(struct ref *ref);
-struct sha1_array;
+struct oid_array;
extern struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
struct ref **list, unsigned int flags,
- struct sha1_array *extra_have,
- struct sha1_array *shallow);
+ struct oid_array *extra_have,
+ struct oid_array *shallow);
int resolve_remote_symref(struct ref *ref, struct ref *list);
int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid);
};
extern int parseopt_push_cas_option(const struct option *, const char *arg, int unset);
-extern int parse_push_cas_option(struct push_cas_option *, const char *arg, int unset);
extern int is_empty_cas(const struct push_cas_option *);
void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
/*
* Make a pack stream and spit it out into file descriptor fd
*/
-static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, struct send_pack_args *args)
+static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struct send_pack_args *args)
{
/*
* The child becomes pack-objects --revs; we feed
*/
po_in = xfdopen(po.in, "w");
for (i = 0; i < extra->nr; i++)
- feed_object(extra->sha1[i], po_in, 1);
+ feed_object(extra->oid[i].hash, po_in, 1);
while (refs) {
if (!is_null_oid(&refs->old_oid))
int send_pack(struct send_pack_args *args,
int fd[], struct child_process *conn,
struct ref *remote_refs,
- struct sha1_array *extra_have)
+ struct oid_array *extra_have)
{
int in = fd[0];
int out = fd[1];
int send_pack(struct send_pack_args *args,
int fd[], struct child_process *conn,
- struct ref *remote_refs, struct sha1_array *extra_have);
+ struct ref *remote_refs, struct oid_array *extra_have);
#endif
#include "sha1-array.h"
#include "sha1-lookup.h"
-void sha1_array_append(struct sha1_array *array, const unsigned char *sha1)
+void oid_array_append(struct oid_array *array, const struct object_id *oid)
{
- ALLOC_GROW(array->sha1, array->nr + 1, array->alloc);
- hashcpy(array->sha1[array->nr++], sha1);
+ ALLOC_GROW(array->oid, array->nr + 1, array->alloc);
+ oidcpy(&array->oid[array->nr++], oid);
array->sorted = 0;
}
static int void_hashcmp(const void *a, const void *b)
{
- return hashcmp(a, b);
+ return oidcmp(a, b);
}
-static void sha1_array_sort(struct sha1_array *array)
+static void oid_array_sort(struct oid_array *array)
{
- QSORT(array->sha1, array->nr, void_hashcmp);
+ QSORT(array->oid, array->nr, void_hashcmp);
array->sorted = 1;
}
static const unsigned char *sha1_access(size_t index, void *table)
{
- unsigned char (*array)[20] = table;
- return array[index];
+ struct object_id *array = table;
+ return array[index].hash;
}
-int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1)
+int oid_array_lookup(struct oid_array *array, const struct object_id *oid)
{
if (!array->sorted)
- sha1_array_sort(array);
- return sha1_pos(sha1, array->sha1, array->nr, sha1_access);
+ oid_array_sort(array);
+ return sha1_pos(oid->hash, array->oid, array->nr, sha1_access);
}
-void sha1_array_clear(struct sha1_array *array)
+void oid_array_clear(struct oid_array *array)
{
- free(array->sha1);
- array->sha1 = NULL;
+ free(array->oid);
+ array->oid = NULL;
array->nr = 0;
array->alloc = 0;
array->sorted = 0;
}
-int sha1_array_for_each_unique(struct sha1_array *array,
- for_each_sha1_fn fn,
+int oid_array_for_each_unique(struct oid_array *array,
+ for_each_oid_fn fn,
void *data)
{
int i;
if (!array->sorted)
- sha1_array_sort(array);
+ oid_array_sort(array);
for (i = 0; i < array->nr; i++) {
int ret;
- if (i > 0 && !hashcmp(array->sha1[i], array->sha1[i-1]))
+ if (i > 0 && !oidcmp(array->oid + i, array->oid + i - 1))
continue;
- ret = fn(array->sha1[i], data);
+ ret = fn(array->oid + i, data);
if (ret)
return ret;
}
#ifndef SHA1_ARRAY_H
#define SHA1_ARRAY_H
-struct sha1_array {
- unsigned char (*sha1)[20];
+struct oid_array {
+ struct object_id *oid;
int nr;
int alloc;
int sorted;
};
-#define SHA1_ARRAY_INIT { NULL, 0, 0, 0 }
+#define OID_ARRAY_INIT { NULL, 0, 0, 0 }
-void sha1_array_append(struct sha1_array *array, const unsigned char *sha1);
-int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1);
-void sha1_array_clear(struct sha1_array *array);
+void oid_array_append(struct oid_array *array, const struct object_id *oid);
+int oid_array_lookup(struct oid_array *array, const struct object_id *oid);
+void oid_array_clear(struct oid_array *array);
-typedef int (*for_each_sha1_fn)(const unsigned char sha1[20],
- void *data);
-int sha1_array_for_each_unique(struct sha1_array *array,
- for_each_sha1_fn fn,
+typedef int (*for_each_oid_fn)(const struct object_id *oid,
+ void *data);
+int oid_array_for_each_unique(struct oid_array *array,
+ for_each_oid_fn fn,
void *data);
#endif /* SHA1_ARRAY_H */
if (!hashcmp(sha1, p->bad_object_sha1 + GIT_SHA1_RAWSZ * i))
return;
p->bad_object_sha1 = xrealloc(p->bad_object_sha1,
- st_mult(GIT_SHA1_RAWSZ,
+ st_mult(GIT_MAX_RAWSZ,
st_add(p->num_bad_objects, 1)));
hashcpy(p->bad_object_sha1 + GIT_SHA1_RAWSZ * p->num_bad_objects, sha1);
p->num_bad_objects++;
if (status && oi->typep)
*oi->typep = status;
strbuf_release(&hdrbuf);
- return 0;
+ return (status < 0) ? status : 0;
}
int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
strbuf_addf(path, "/%s", de->d_name);
if (strlen(de->d_name) == GIT_SHA1_HEXSZ - 2) {
- char hex[GIT_SHA1_HEXSZ+1];
+ char hex[GIT_MAX_HEXSZ+1];
struct object_id oid;
- snprintf(hex, sizeof(hex), "%02x%s",
- subdir_nr, de->d_name);
+ xsnprintf(hex, sizeof(hex), "%02x%s",
+ subdir_nr, de->d_name);
if (!get_oid_hex(hex, &oid)) {
if (obj_cb) {
r = obj_cb(&oid, path->buf, data);
const unsigned char *expected_sha1)
{
git_SHA_CTX c;
- unsigned char real_sha1[GIT_SHA1_RAWSZ];
+ unsigned char real_sha1[GIT_MAX_RAWSZ];
unsigned char buf[4096];
unsigned long total_read;
int status = Z_OK;
static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);
-typedef int (*disambiguate_hint_fn)(const unsigned char *, void *);
+typedef int (*disambiguate_hint_fn)(const struct object_id *, void *);
struct disambiguate_state {
int len; /* length of prefix in hex chars */
- char hex_pfx[GIT_SHA1_HEXSZ + 1];
- unsigned char bin_pfx[GIT_SHA1_RAWSZ];
+ char hex_pfx[GIT_MAX_HEXSZ + 1];
+ struct object_id bin_pfx;
disambiguate_hint_fn fn;
void *cb_data;
- unsigned char candidate[GIT_SHA1_RAWSZ];
+ struct object_id candidate;
unsigned candidate_exists:1;
unsigned candidate_checked:1;
unsigned candidate_ok:1;
unsigned always_call_fn:1;
};
-static void update_candidates(struct disambiguate_state *ds, const unsigned char *current)
+static void update_candidates(struct disambiguate_state *ds, const struct object_id *current)
{
if (ds->always_call_fn) {
ds->ambiguous = ds->fn(current, ds->cb_data) ? 1 : 0;
}
if (!ds->candidate_exists) {
/* this is the first candidate */
- hashcpy(ds->candidate, current);
+ oidcpy(&ds->candidate, current);
ds->candidate_exists = 1;
return;
- } else if (!hashcmp(ds->candidate, current)) {
+ } else if (!oidcmp(&ds->candidate, current)) {
/* the same as what we already have seen */
return;
}
}
if (!ds->candidate_checked) {
- ds->candidate_ok = ds->fn(ds->candidate, ds->cb_data);
+ ds->candidate_ok = ds->fn(&ds->candidate, ds->cb_data);
ds->disambiguate_fn_used = 1;
ds->candidate_checked = 1;
}
if (!ds->candidate_ok) {
/* discard the candidate; we know it does not satisfy fn */
- hashcpy(ds->candidate, current);
+ oidcpy(&ds->candidate, current);
ds->candidate_checked = 0;
return;
}
static void find_short_object_filename(struct disambiguate_state *ds)
{
struct alternate_object_database *alt;
- char hex[GIT_SHA1_HEXSZ];
+ char hex[GIT_MAX_HEXSZ];
static struct alternate_object_database *fakeent;
if (!fakeent) {
continue;
while (!ds->ambiguous && (de = readdir(dir)) != NULL) {
- unsigned char sha1[20];
+ struct object_id oid;
- if (strlen(de->d_name) != 38)
+ if (strlen(de->d_name) != GIT_SHA1_HEXSZ - 2)
continue;
if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2))
continue;
- memcpy(hex + 2, de->d_name, 38);
- if (!get_sha1_hex(hex, sha1))
- update_candidates(ds, sha1);
+ memcpy(hex + 2, de->d_name, GIT_SHA1_HEXSZ - 2);
+ if (!get_oid_hex(hex, &oid))
+ update_candidates(ds, &oid);
}
closedir(dir);
}
struct disambiguate_state *ds)
{
uint32_t num, last, i, first = 0;
- const unsigned char *current = NULL;
+ const struct object_id *current = NULL;
open_pack_index(p);
num = p->num_objects;
int cmp;
current = nth_packed_object_sha1(p, mid);
- cmp = hashcmp(ds->bin_pfx, current);
+ cmp = hashcmp(ds->bin_pfx.hash, current);
if (!cmp) {
first = mid;
break;
* 0, 1 or more objects that actually match(es).
*/
for (i = first; i < num && !ds->ambiguous; i++) {
- current = nth_packed_object_sha1(p, i);
- if (!match_sha(ds->len, ds->bin_pfx, current))
+ struct object_id oid;
+ current = nth_packed_object_oid(&oid, p, i);
+ if (!match_sha(ds->len, ds->bin_pfx.hash, current->hash))
break;
update_candidates(ds, current);
}
* same repository!
*/
ds->candidate_ok = (!ds->disambiguate_fn_used ||
- ds->fn(ds->candidate, ds->cb_data));
+ ds->fn(&ds->candidate, ds->cb_data));
if (!ds->candidate_ok)
return SHORT_NAME_AMBIGUOUS;
- hashcpy(sha1, ds->candidate);
+ hashcpy(sha1, ds->candidate.hash);
return 0;
}
-static int disambiguate_commit_only(const unsigned char *sha1, void *cb_data_unused)
+static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(sha1, NULL);
+ int kind = sha1_object_info(oid->hash, NULL);
return kind == OBJ_COMMIT;
}
-static int disambiguate_committish_only(const unsigned char *sha1, void *cb_data_unused)
+static int disambiguate_committish_only(const struct object_id *oid, void *cb_data_unused)
{
struct object *obj;
int kind;
- kind = sha1_object_info(sha1, NULL);
+ kind = sha1_object_info(oid->hash, NULL);
if (kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
return 0;
/* We need to do this the hard way... */
- obj = deref_tag(parse_object(sha1), NULL, 0);
+ obj = deref_tag(parse_object(oid->hash), NULL, 0);
if (obj && obj->type == OBJ_COMMIT)
return 1;
return 0;
}
-static int disambiguate_tree_only(const unsigned char *sha1, void *cb_data_unused)
+static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(sha1, NULL);
+ int kind = sha1_object_info(oid->hash, NULL);
return kind == OBJ_TREE;
}
-static int disambiguate_treeish_only(const unsigned char *sha1, void *cb_data_unused)
+static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_unused)
{
struct object *obj;
int kind;
- kind = sha1_object_info(sha1, NULL);
+ kind = sha1_object_info(oid->hash, NULL);
if (kind == OBJ_TREE || kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
return 0;
/* We need to do this the hard way... */
- obj = deref_tag(parse_object(sha1), NULL, 0);
+ obj = deref_tag(parse_object(oid->hash), NULL, 0);
if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
return 1;
return 0;
}
-static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unused)
+static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(sha1, NULL);
+ int kind = sha1_object_info(oid->hash, NULL);
return kind == OBJ_BLOB;
}
ds->hex_pfx[i] = c;
if (!(i & 1))
val <<= 4;
- ds->bin_pfx[i >> 1] |= val;
+ ds->bin_pfx.hash[i >> 1] |= val;
}
ds->len = len;
return 0;
}
-static int show_ambiguous_object(const unsigned char *sha1, void *data)
+static int show_ambiguous_object(const struct object_id *oid, void *data)
{
const struct disambiguate_state *ds = data;
struct strbuf desc = STRBUF_INIT;
int type;
- if (ds->fn && !ds->fn(sha1, ds->cb_data))
+
+ if (ds->fn && !ds->fn(oid, ds->cb_data))
return 0;
- type = sha1_object_info(sha1, NULL);
+ type = sha1_object_info(oid->hash, NULL);
if (type == OBJ_COMMIT) {
- struct commit *commit = lookup_commit(sha1);
+ struct commit *commit = lookup_commit(oid->hash);
if (commit) {
struct pretty_print_context pp = {0};
pp.date_mode.type = DATE_SHORT;
format_commit_message(commit, " %ad - %s", &desc, &pp);
}
} else if (type == OBJ_TAG) {
- struct tag *tag = lookup_tag(sha1);
+ struct tag *tag = lookup_tag(oid->hash);
if (!parse_tag(tag) && tag->tag)
strbuf_addf(&desc, " %s", tag->tag);
}
advise(" %s %s%s",
- find_unique_abbrev(sha1, DEFAULT_ABBREV),
+ find_unique_abbrev(oid->hash, DEFAULT_ABBREV),
typename(type) ? typename(type) : "unknown type",
desc.buf);
return status;
}
-static int collect_ambiguous(const unsigned char *sha1, void *data)
+static int collect_ambiguous(const struct object_id *oid, void *data)
{
- sha1_array_append(data, sha1);
+ oid_array_append(data, oid);
return 0;
}
int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
{
- struct sha1_array collect = SHA1_ARRAY_INIT;
+ struct oid_array collect = OID_ARRAY_INIT;
struct disambiguate_state ds;
int ret;
find_short_object_filename(&ds);
find_short_packed_object(&ds);
- ret = sha1_array_for_each_unique(&collect, fn, cb_data);
- sha1_array_clear(&collect);
+ ret = oid_array_for_each_unique(&collect, fn, cb_data);
+ oid_array_clear(&collect);
return ret;
}
const char *find_unique_abbrev(const unsigned char *sha1, int len)
{
static int bufno;
- static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
+ static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
char *hex = hexbuffer[bufno];
bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
find_unique_abbrev_r(hex, sha1, len);
}
static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol,
- const struct sha1_array *extra,
+ const struct oid_array *extra,
unsigned flags)
{
struct write_shallow_data data;
if (!extra)
return data.count;
for (i = 0; i < extra->nr; i++) {
- strbuf_addstr(out, sha1_to_hex(extra->sha1[i]));
+ strbuf_addstr(out, oid_to_hex(extra->oid + i));
strbuf_addch(out, '\n');
data.count++;
}
}
int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
- const struct sha1_array *extra)
+ const struct oid_array *extra)
{
return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
}
static struct tempfile temporary_shallow;
-const char *setup_temporary_shallow(const struct sha1_array *extra)
+const char *setup_temporary_shallow(const struct oid_array *extra)
{
struct strbuf sb = STRBUF_INIT;
int fd;
void setup_alternate_shallow(struct lock_file *shallow_lock,
const char **alternate_shallow_file,
- const struct sha1_array *extra)
+ const struct oid_array *extra)
{
struct strbuf sb = STRBUF_INIT;
int fd;
* Step 1, split sender shallow commits into "ours" and "theirs"
* Step 2, clean "ours" based on .git/shallow
*/
-void prepare_shallow_info(struct shallow_info *info, struct sha1_array *sa)
+void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)
{
int i;
trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n");
ALLOC_ARRAY(info->ours, sa->nr);
ALLOC_ARRAY(info->theirs, sa->nr);
for (i = 0; i < sa->nr; i++) {
- if (has_sha1_file(sa->sha1[i])) {
+ if (has_object_file(sa->oid + i)) {
struct commit_graft *graft;
- graft = lookup_commit_graft(sa->sha1[i]);
+ graft = lookup_commit_graft(sa->oid[i].hash);
if (graft && graft->nr_parent < 0)
continue;
info->ours[info->nr_ours++] = i;
void remove_nonexistent_theirs_shallow(struct shallow_info *info)
{
- unsigned char (*sha1)[20] = info->shallow->sha1;
+ struct object_id *oid = info->shallow->oid;
int i, dst;
trace_printf_key(&trace_shallow, "shallow: remove_nonexistent_theirs_shallow\n");
for (i = dst = 0; i < info->nr_theirs; i++) {
if (i != dst)
info->theirs[dst] = info->theirs[i];
- if (has_sha1_file(sha1[info->theirs[i]]))
+ if (has_object_file(oid + info->theirs[i]))
dst++;
}
info->nr_theirs = dst;
void assign_shallow_commits_to_refs(struct shallow_info *info,
uint32_t **used, int *ref_status)
{
- unsigned char (*sha1)[20] = info->shallow->sha1;
- struct sha1_array *ref = info->ref;
+ struct object_id *oid = info->shallow->oid;
+ struct oid_array *ref = info->ref;
unsigned int i, nr;
int *shallow, nr_shallow = 0;
struct paint_info pi;
/* Mark potential bottoms so we won't go out of bound */
for (i = 0; i < nr_shallow; i++) {
- struct commit *c = lookup_commit(sha1[shallow[i]]);
+ struct commit *c = lookup_commit(oid[shallow[i]].hash);
c->object.flags |= BOTTOM;
}
for (i = 0; i < ref->nr; i++)
- paint_down(&pi, ref->sha1[i], i);
+ paint_down(&pi, ref->oid[i].hash, i);
if (used) {
int bitmap_size = ((pi.nr_bits + 31) / 32) * sizeof(uint32_t);
memset(used, 0, sizeof(*used) * info->shallow->nr);
for (i = 0; i < nr_shallow; i++) {
- const struct commit *c = lookup_commit(sha1[shallow[i]]);
+ const struct commit *c = lookup_commit(oid[shallow[i]].hash);
uint32_t **map = ref_bitmap_at(&pi.ref_bitmap, c);
if (*map)
used[shallow[i]] = xmemdupz(*map, bitmap_size);
struct ref_bitmap *ref_bitmap,
int *ref_status)
{
- unsigned char (*sha1)[20] = info->shallow->sha1;
+ struct object_id *oid = info->shallow->oid;
struct commit *c;
uint32_t **bitmap;
int dst, i, j;
for (i = dst = 0; i < info->nr_theirs; i++) {
if (i != dst)
info->theirs[dst] = info->theirs[i];
- c = lookup_commit(sha1[info->theirs[i]]);
+ c = lookup_commit(oid[info->theirs[i]].hash);
bitmap = ref_bitmap_at(ref_bitmap, c);
if (!*bitmap)
continue;
for (i = dst = 0; i < info->nr_ours; i++) {
if (i != dst)
info->ours[dst] = info->ours[i];
- c = lookup_commit(sha1[info->ours[i]]);
+ c = lookup_commit(oid[info->ours[i]].hash);
bitmap = ref_bitmap_at(ref_bitmap, c);
if (!*bitmap)
continue;
int delayed_reachability_test(struct shallow_info *si, int c)
{
if (si->need_reachability_test[c]) {
- struct commit *commit = lookup_commit(si->shallow->sha1[c]);
+ struct commit *commit = lookup_commit(si->shallow->oid[c].hash);
if (!si->commits) {
struct commit_array ca;
static int parallel_jobs = 1;
static struct string_list changed_submodule_paths = STRING_LIST_INIT_NODUP;
static int initialized_fetch_ref_tips;
-static struct sha1_array ref_tips_before_fetch;
-static struct sha1_array ref_tips_after_fetch;
+static struct oid_array ref_tips_before_fetch;
+static struct oid_array ref_tips_after_fetch;
/*
* The following flag is set if the .gitmodules file is unmerged. We then
if (!(dirty_submodule & DIRTY_SUBMODULE_MODIFIED))
argv_array_push(&cp.args, oid_to_hex(new));
+ prepare_submodule_repo_env(&cp.env_array);
if (run_command(&cp))
fprintf(f, "(diff failed)\n");
return 1;
}
-static int append_sha1_to_argv(const unsigned char sha1[20], void *data)
+static int append_oid_to_argv(const struct object_id *oid, void *data)
{
struct argv_array *argv = data;
- argv_array_push(argv, sha1_to_hex(sha1));
+ argv_array_push(argv, oid_to_hex(oid));
return 0;
}
-static int check_has_commit(const unsigned char sha1[20], void *data)
+static int check_has_commit(const struct object_id *oid, void *data)
{
int *has_commit = data;
- if (!lookup_commit_reference(sha1))
+ if (!lookup_commit_reference(oid->hash))
*has_commit = 0;
return 0;
}
-static int submodule_has_commits(const char *path, struct sha1_array *commits)
+static int submodule_has_commits(const char *path, struct oid_array *commits)
{
int has_commit = 1;
if (add_submodule_odb(path))
return 0;
- sha1_array_for_each_unique(commits, check_has_commit, &has_commit);
+ oid_array_for_each_unique(commits, check_has_commit, &has_commit);
return has_commit;
}
-static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
+static int submodule_needs_pushing(const char *path, struct oid_array *commits)
{
if (!submodule_has_commits(path, commits))
/*
int needs_pushing = 0;
argv_array_push(&cp.args, "rev-list");
- sha1_array_for_each_unique(commits, append_sha1_to_argv, &cp.args);
+ oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args);
argv_array_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
prepare_submodule_repo_env(&cp.env_array);
return 0;
}
-static struct sha1_array *submodule_commits(struct string_list *submodules,
+static struct oid_array *submodule_commits(struct string_list *submodules,
const char *path)
{
struct string_list_item *item;
item = string_list_insert(submodules, path);
if (item->util)
- return (struct sha1_array *) item->util;
+ return (struct oid_array *) item->util;
- /* NEEDSWORK: should we have sha1_array_init()? */
- item->util = xcalloc(1, sizeof(struct sha1_array));
- return (struct sha1_array *) item->util;
+ /* NEEDSWORK: should we have oid_array_init()? */
+ item->util = xcalloc(1, sizeof(struct oid_array));
+ return (struct oid_array *) item->util;
}
static void collect_submodules_from_diff(struct diff_queue_struct *q,
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
- struct sha1_array *commits;
+ struct oid_array *commits;
if (!S_ISGITLINK(p->two->mode))
continue;
commits = submodule_commits(submodules, p->two->path);
- sha1_array_append(commits, p->two->oid.hash);
+ oid_array_append(commits, &p->two->oid);
}
}
{
struct string_list_item *item;
for_each_string_list_item(item, submodules)
- sha1_array_clear((struct sha1_array *) item->util);
+ oid_array_clear((struct oid_array *) item->util);
string_list_clear(submodules, 1);
}
-int find_unpushed_submodules(struct sha1_array *commits,
+int find_unpushed_submodules(struct oid_array *commits,
const char *remotes_name, struct string_list *needs_pushing)
{
struct rev_info rev;
/* argv.argv[0] will be ignored by setup_revisions */
argv_array_push(&argv, "find_unpushed_submodules");
- sha1_array_for_each_unique(commits, append_sha1_to_argv, &argv);
+ oid_array_for_each_unique(commits, append_oid_to_argv, &argv);
argv_array_push(&argv, "--not");
argv_array_pushf(&argv, "--remotes=%s", remotes_name);
argv_array_clear(&argv);
for_each_string_list_item(submodule, &submodules) {
- struct sha1_array *commits = (struct sha1_array *) submodule->util;
+ struct oid_array *commits = (struct oid_array *) submodule->util;
if (submodule_needs_pushing(submodule->string, commits))
string_list_insert(needs_pushing, submodule->string);
die("process for submodule '%s' failed", path);
}
-int push_unpushed_submodules(struct sha1_array *commits,
+int push_unpushed_submodules(struct oid_array *commits,
const struct remote *remote,
const char **refspec, int refspec_nr,
const struct string_list *push_options,
static int add_sha1_to_array(const char *ref, const struct object_id *oid,
int flags, void *data)
{
- sha1_array_append(data, oid->hash);
+ oid_array_append(data, oid);
return 0;
}
-void check_for_new_submodule_commits(unsigned char new_sha1[20])
+void check_for_new_submodule_commits(struct object_id *oid)
{
if (!initialized_fetch_ref_tips) {
for_each_ref(add_sha1_to_array, &ref_tips_before_fetch);
initialized_fetch_ref_tips = 1;
}
- sha1_array_append(&ref_tips_after_fetch, new_sha1);
+ oid_array_append(&ref_tips_after_fetch, oid);
}
-static int add_sha1_to_argv(const unsigned char sha1[20], void *data)
+static int add_oid_to_argv(const struct object_id *oid, void *data)
{
- argv_array_push(data, sha1_to_hex(sha1));
+ argv_array_push(data, oid_to_hex(oid));
return 0;
}
init_revisions(&rev, NULL);
argv_array_push(&argv, "--"); /* argv[0] program name */
- sha1_array_for_each_unique(&ref_tips_after_fetch,
- add_sha1_to_argv, &argv);
+ oid_array_for_each_unique(&ref_tips_after_fetch,
+ add_oid_to_argv, &argv);
argv_array_push(&argv, "--not");
- sha1_array_for_each_unique(&ref_tips_before_fetch,
- add_sha1_to_argv, &argv);
+ oid_array_for_each_unique(&ref_tips_before_fetch,
+ add_oid_to_argv, &argv);
setup_revisions(argv.argc, argv.argv, &rev, NULL);
if (prepare_revision_walk(&rev))
die("revision walk setup failed");
}
argv_array_clear(&argv);
- sha1_array_clear(&ref_tips_before_fetch);
- sha1_array_clear(&ref_tips_after_fetch);
+ oid_array_clear(&ref_tips_before_fetch);
+ oid_array_clear(&ref_tips_after_fetch);
initialized_fetch_ref_tips = 0;
}
unsigned is_submodule_modified(const char *path, int ignore_untracked)
{
- ssize_t len;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *argv[] = {
- "status",
- "--porcelain",
- NULL,
- NULL,
- };
struct strbuf buf = STRBUF_INIT;
+ FILE *fp;
unsigned dirty_submodule = 0;
- const char *line, *next_line;
const char *git_dir;
+ int ignore_cp_exit_code = 0;
strbuf_addf(&buf, "%s/.git", path);
git_dir = read_gitfile(buf.buf);
if (!git_dir)
git_dir = buf.buf;
- if (!is_directory(git_dir)) {
+ if (!is_git_directory(git_dir)) {
+ if (is_directory(git_dir))
+ die(_("'%s' not recognized as a git repository"), git_dir);
strbuf_release(&buf);
/* The submodule is not checked out, so it is not modified */
return 0;
-
}
strbuf_reset(&buf);
+ argv_array_pushl(&cp.args, "status", "--porcelain=2", NULL);
if (ignore_untracked)
- argv[2] = "-uno";
+ argv_array_push(&cp.args, "-uno");
- cp.argv = argv;
prepare_submodule_repo_env(&cp.env_array);
cp.git_cmd = 1;
cp.no_stdin = 1;
cp.out = -1;
cp.dir = path;
if (start_command(&cp))
- die("Could not run 'git status --porcelain' in submodule %s", path);
+ die("Could not run 'git status --porcelain=2' in submodule %s", path);
- len = strbuf_read(&buf, cp.out, 1024);
- line = buf.buf;
- while (len > 2) {
- if ((line[0] == '?') && (line[1] == '?')) {
+ fp = xfdopen(cp.out, "r");
+ while (strbuf_getwholeline(&buf, fp, '\n') != EOF) {
+ /* regular untracked files */
+ if (buf.buf[0] == '?')
dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
- if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
- break;
- } else {
- dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
- if (ignore_untracked ||
- (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED))
- break;
+
+ if (buf.buf[0] == 'u' ||
+ buf.buf[0] == '1' ||
+ buf.buf[0] == '2') {
+ /* T = line type, XY = status, SSSS = submodule state */
+ if (buf.len < strlen("T XY SSSS"))
+ die("BUG: invalid status --porcelain=2 line %s",
+ buf.buf);
+
+ if (buf.buf[5] == 'S' && buf.buf[8] == 'U')
+ /* nested untracked file */
+ dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
+
+ if (buf.buf[0] == 'u' ||
+ buf.buf[0] == '2' ||
+ memcmp(buf.buf + 5, "S..U", 4))
+ /* other change */
+ dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
}
- next_line = strchr(line, '\n');
- if (!next_line)
+
+ if ((dirty_submodule & DIRTY_SUBMODULE_MODIFIED) &&
+ ((dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) ||
+ ignore_untracked)) {
+ /*
+ * We're not interested in any further information from
+ * the child any more, neither output nor its exit code.
+ */
+ ignore_cp_exit_code = 1;
break;
- next_line++;
- len -= (next_line - line);
- line = next_line;
+ }
}
- close(cp.out);
+ fclose(fp);
- if (finish_command(&cp))
- die("'git status --porcelain' failed in submodule %s", path);
+ if (finish_command(&cp) && !ignore_cp_exit_code)
+ die("'git status --porcelain=2' failed in submodule %s", path);
strbuf_release(&buf);
return dirty_submodule;
memset(&rev_opts, 0, sizeof(rev_opts));
/* get all revisions that merge commit a */
- snprintf(merged_revision, sizeof(merged_revision), "^%s",
+ xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
oid_to_hex(&a->object.oid));
init_revisions(&revs, NULL);
rev_opts.submodule = path;
struct diff_options;
struct argv_array;
-struct sha1_array;
+struct oid_array;
struct remote;
enum {
* and it should be updated. Returns NULL otherwise.
*/
extern const struct submodule *submodule_from_ce(const struct cache_entry *ce);
-extern void check_for_new_submodule_commits(unsigned char new_sha1[20]);
+extern void check_for_new_submodule_commits(struct object_id *oid);
extern int fetch_populated_submodules(const struct argv_array *options,
const char *prefix, int command_line_option,
int quiet, int max_parallel_jobs);
const unsigned char base[20],
const unsigned char a[20],
const unsigned char b[20], int search);
-extern int find_unpushed_submodules(struct sha1_array *commits,
+extern int find_unpushed_submodules(struct oid_array *commits,
const char *remotes_name,
struct string_list *needs_pushing);
-extern int push_unpushed_submodules(struct sha1_array *commits,
+extern int push_unpushed_submodules(struct oid_array *commits,
const struct remote *remote,
const char **refspec, int refspec_nr,
const struct string_list *push_options,
#include "cache.h"
#include "sha1-array.h"
-static int print_sha1(const unsigned char sha1[20], void *data)
+static int print_oid(const struct object_id *oid, void *data)
{
- puts(sha1_to_hex(sha1));
+ puts(oid_to_hex(oid));
return 0;
}
int cmd_main(int argc, const char **argv)
{
- struct sha1_array array = SHA1_ARRAY_INIT;
+ struct oid_array array = OID_ARRAY_INIT;
struct strbuf line = STRBUF_INIT;
while (strbuf_getline(&line, stdin) != EOF) {
const char *arg;
- unsigned char sha1[20];
+ struct object_id oid;
if (skip_prefix(line.buf, "append ", &arg)) {
- if (get_sha1_hex(arg, sha1))
+ if (get_oid_hex(arg, &oid))
die("not a hexadecimal SHA1: %s", arg);
- sha1_array_append(&array, sha1);
+ oid_array_append(&array, &oid);
} else if (skip_prefix(line.buf, "lookup ", &arg)) {
- if (get_sha1_hex(arg, sha1))
+ if (get_oid_hex(arg, &oid))
die("not a hexadecimal SHA1: %s", arg);
- printf("%d\n", sha1_array_lookup(&array, sha1));
+ printf("%d\n", oid_array_lookup(&array, &oid));
} else if (!strcmp(line.buf, "clear"))
- sha1_array_clear(&array);
+ oid_array_clear(&array);
else if (!strcmp(line.buf, "for_each_unique"))
- sha1_array_for_each_unique(&array, print_sha1, NULL);
+ oid_array_for_each_unique(&array, print_oid, NULL);
else
die("unknown command: %s", line.buf);
}
cd bit-error &&
test_commit content &&
corrupt_byte HEAD:content.t 10
+ ) &&
+ git init no-bit-error &&
+ (
+ # distinct commit from bit-error, but containing a
+ # non-corrupted version of the same blob
+ cd no-bit-error &&
+ test_tick &&
+ test_commit content
)
'
)
'
+test_expect_success 'getting type of a corrupt blob fails' '
+ (
+ cd bit-error &&
+ test_must_fail git cat-file -s HEAD:content.t
+ )
+'
+
test_expect_success 'read-tree -u detects bit-errors in blobs' '
(
cd bit-error &&
test_must_fail git clone --local misnamed misnamed-checkout
'
+test_expect_success 'fetch into corrupted repo with index-pack' '
+ (
+ cd bit-error &&
+ test_must_fail git -c transfer.unpackLimit=1 \
+ fetch ../no-bit-error 2>stderr &&
+ test_i18ngrep ! -i collision stderr
+ )
+'
+
test_done
test_must_fail git branch --merged 0000000000000000000000000000000000000000
'
+test_expect_success '--merged is incompatible with --no-merged' '
+ test_must_fail git branch --merged HEAD --no-merged HEAD
+'
+
test_expect_success 'tracking with unexpected .fetch refspec' '
rm -rf a b c d &&
git init a &&
#!/bin/sh
-test_description='branch --contains <commit>, --merged, and --no-merged'
+test_description='branch --contains <commit>, --no-contains <commit> --merged, and --no-merged'
. ./test-lib.sh
'
+test_expect_success 'branch --no-contains=master' '
+
+ git branch --no-contains=master >actual &&
+ >expect &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'branch --no-contains master' '
+
+ git branch --no-contains master >actual &&
+ >expect &&
+ test_cmp expect actual
+
+'
+
test_expect_success 'branch --contains=side' '
git branch --contains=side >actual &&
'
+test_expect_success 'branch --no-contains=side' '
+
+ git branch --no-contains=side >actual &&
+ {
+ echo " master"
+ } >expect &&
+ test_cmp expect actual
+
+'
+
test_expect_success 'branch --contains with pattern implies --list' '
git branch --contains=master master >actual &&
'
+test_expect_success 'branch --no-contains with pattern implies --list' '
+
+ git branch --no-contains=master master >actual &&
+ >expect &&
+ test_cmp expect actual
+
+'
+
test_expect_success 'side: branch --merged' '
git branch --merged >actual &&
test_expect_success 'implicit --list conflicts with modification options' '
test_must_fail git branch --contains=master -d &&
- test_must_fail git branch --contains=master -m foo
+ test_must_fail git branch --contains=master -m foo &&
+ test_must_fail git branch --no-contains=master -d &&
+ test_must_fail git branch --no-contains=master -m foo
+
+'
+test_expect_success 'Assert that --contains only works on commits, not trees & blobs' '
+ test_must_fail git branch --contains master^{tree} &&
+ blob=$(git hash-object -w --stdin <<-\EOF
+ Some blob
+ EOF
+ ) &&
+ test_must_fail git branch --contains $blob &&
+ test_must_fail git branch --no-contains $blob
'
# We want to set up a case where the walk for the tracking info
test_i18ncmp expect actual
'
+test_expect_success 'branch --contains combined with --no-contains' '
+ git branch --contains zzz --no-contains topic >actual &&
+ cat >expect <<-\EOF &&
+ master
+ side
+ zzz
+ EOF
+ test_cmp expect actual
+
+'
+
test_done
M submod
EOF
+cat >expect.modified_inside <<EOF
+ m submod
+EOF
+
+cat >expect.modified_untracked <<EOF
+ ? submod
+EOF
+
cat >expect.cached <<EOF
D submod
EOF
test -d submod &&
test -f submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- test_cmp expect.modified actual &&
+ test_cmp expect.modified_inside actual &&
git rm -f submod &&
test ! -d submod &&
git status -s -uno --ignore-submodules=none >actual &&
test -d submod &&
test -f submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- test_cmp expect.modified actual &&
+ test_cmp expect.modified_untracked actual &&
git rm -f submod &&
test ! -d submod &&
git status -s -uno --ignore-submodules=none >actual &&
test -d submod &&
test -f submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- test_cmp expect.modified actual &&
+ test_cmp expect.modified_inside actual &&
git rm -f submod &&
test ! -d submod &&
git status -s -uno --ignore-submodules=none >actual &&
test -d submod &&
test -f submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- test_cmp expect.modified actual &&
+ test_cmp expect.modified_inside actual &&
git rm -f submod &&
test ! -d submod &&
git status -s -uno --ignore-submodules=none >actual &&
test -d submod &&
test -f submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- test_cmp expect.modified actual &&
+ test_cmp expect.modified_untracked actual &&
git rm -f submod &&
test ! -d submod &&
git status -s -uno --ignore-submodules=none >actual &&
test_cmp expected actual
'
+test_expect_success 'setup nested submodule' '
+ git submodule add -f ./sm2 &&
+ git commit -a -m "add sm2" &&
+ git -C sm2 submodule add ../sm2 nested &&
+ git -C sm2 commit -a -m "nested sub"
+'
+
+test_expect_success 'move nested submodule HEAD' '
+ echo "nested content" >sm2/nested/file &&
+ git -C sm2/nested add file &&
+ git -C sm2/nested commit --allow-empty -m "new HEAD"
+'
+
+test_expect_success 'diff --submodule=diff with moved nested submodule HEAD' '
+ cat >expected <<-EOF &&
+ Submodule nested a5a65c9..b55928c:
+ diff --git a/nested/file b/nested/file
+ new file mode 100644
+ index 0000000..ca281f5
+ --- /dev/null
+ +++ b/nested/file
+ @@ -0,0 +1 @@
+ +nested content
+ EOF
+ git -C sm2 diff --submodule=diff >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expected actual
+'
+
test_done
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
+. "$TEST_DIRECTORY/lib-terminal.sh"
test_expect_success setup '
'
test_expect_success 'log.decorate configuration' '
- git log --oneline >expect.none &&
+ git log --oneline --no-decorate >expect.none &&
git log --oneline --decorate >expect.short &&
git log --oneline --decorate=full >expect.full &&
'
+test_expect_success TTY 'log output on a TTY' '
+ git log --oneline --decorate >expect.short &&
+
+ test_terminal git log --oneline >actual &&
+ test_cmp expect.short actual
+'
+
test_expect_success 'reflog is expected format' '
git log -g --abbrev-commit --pretty=oneline >expect &&
git reflog >actual &&
test_cmp expect actual
'
+test_expect_success 'filtering with --no-contains' '
+ cat >expect <<-\EOF &&
+ refs/tags/one
+ EOF
+ git for-each-ref --format="%(refname)" --no-contains=two >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with --contains and --no-contains' '
+ cat >expect <<-\EOF &&
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --contains=two --no-contains=three >actual &&
+ test_cmp expect actual
+'
+
test_expect_success '%(color) must fail' '
test_must_fail git for-each-ref --format="%(color)%(refname)"
'
test_cmp expect actual
'
+test_expect_success '--merged is incompatible with --no-merged' '
+ test_must_fail git for-each-ref --merged HEAD --no-merged HEAD
+'
+
test_done
git show-ref --quiet --verify refs/tags/"$1"
}
-# todo: git tag -l now returns always zero, when fixed, change this test
test_expect_success 'listing all tags in an empty tree should succeed' '
git tag -l &&
git tag
git tag
'
+cat >expect <<EOF
+mytag
+EOF
+test_expect_success 'Multiple -l or --list options are equivalent to one -l option' '
+ git tag -l -l >actual &&
+ test_cmp expect actual &&
+ git tag --list --list >actual &&
+ test_cmp expect actual &&
+ git tag --list -l --list >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'listing all tags if one exists should output that tag' '
test $(git tag -l) = mytag &&
test $(git tag) = mytag
'listing a tag using a matching pattern should output that tag' \
'test $(git tag -l mytag) = mytag'
-# todo: git tag -l now returns always zero, when fixed, change this test
test_expect_success \
- 'listing tags using a non-matching pattern should suceed' \
+ 'listing tags using a non-matching pattern should succeed' \
'git tag -l xxx'
test_expect_success \
test_cmp expect actual
'
+# Between v1.7.7 & v2.13.0 a fair reading of the git-tag documentation
+# could leave you with the impression that "-l <pattern> -l <pattern>"
+# was how we wanted to accept multiple patterns.
+#
+# This test should not imply that this is a sane thing to support. but
+# since the documentation was worded like it was let's at least find
+# out if we're going to break this long-documented form of taking
+# multiple patterns.
+test_expect_success 'tag -l <pattern> -l <pattern> works, as our buggy documentation previously suggested' '
+ git tag -l "v1*" -l "v0*" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'listing tags in column' '
COLUMNS=40 git tag -l --column=row >actual &&
cat >expected <<\EOF &&
git tag -n0 -l tag-one-line >actual &&
test_cmp expect actual &&
+ git tag -n0 | grep "^tag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 tag-one-line >actual &&
+ test_cmp expect actual &&
+
echo "tag-one-line A msg" >expect &&
git tag -n1 -l | grep "^tag-one-line" >actual &&
test_cmp expect actual &&
test_cmp expect actual
'
+test_expect_success 'The -n 100 invocation means -n --list 100, not -n100' '
+ >expect &&
+ git tag -n 100 >actual &&
+ test_cmp expect actual &&
+
+ git tag -m "A msg" 100 &&
+ echo "100 A msg" >expect &&
+ git tag -n 100 >actual &&
+ test_cmp expect actual
+'
+
test_expect_success \
'listing the zero-lines message of a non-signed tag should succeed' '
git tag -m "" tag-zero-lines &&
test_cmp expected actual
"
+# All the --contains tests above, but with --no-contains
+test_expect_success 'checking that first commit is not listed in any tag with --no-contains (hash)' "
+ >expected &&
+ git tag -l --no-contains $hash1 v* >actual &&
+ test_cmp expected actual
+"
+
+test_expect_success 'checking that first commit is in all tags (tag)' "
+ git tag -l --no-contains v1.0 v* >actual &&
+ test_cmp expected actual
+"
+
+test_expect_success 'checking that first commit is in all tags (relative)' "
+ git tag -l --no-contains HEAD~2 v* >actual &&
+ test_cmp expected actual
+"
+
cat > expected <<EOF
v2.0
EOF
test_cmp expected actual
"
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+EOF
+
+test_expect_success 'inverse of the last test, with --no-contains' "
+ git tag -l --no-contains $hash2 v* >actual &&
+ test_cmp expected actual
+"
cat > expected <<EOF
EOF
test_cmp expected actual
"
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+v2.0
+EOF
+
+test_expect_success 'conversely --no-contains on the third commit lists all tags' "
+ git tag -l --no-contains $hash3 v* >actual &&
+ test_cmp expected actual
+"
+
# how about a simple merge?
test_expect_success 'creating simple branch' '
test_cmp expected actual
"
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+v2.0
+EOF
+
+test_expect_success 'checking that branch head with --no-contains lists all but one tag' "
+ git tag -l --no-contains $hash4 v* >actual &&
+ test_cmp expected actual
+"
+
test_expect_success 'merging original branch into this branch' '
git merge --strategy=ours master &&
git tag v4.0
test_cmp expected actual
"
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+v2.0
+v3.0
+EOF
+
+test_expect_success 'checking that original branch head with --no-contains lists all but one tag now' "
+ git tag -l --no-contains $hash3 v* >actual &&
+ test_cmp expected actual
+"
+
cat > expected <<EOF
v0.2.1
v1.0
test_cmp expected actual
"
+test_expect_success 'checking that --contains can be used in non-list mode' '
+ git tag --contains $hash1 v* >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'checking that initial commit is in all tags with --no-contains' "
+ >expected &&
+ git tag -l --no-contains $hash1 v* >actual &&
+ test_cmp expected actual
+"
+
# mixing modes and options:
test_expect_success 'mixing incompatibles modes and options is forbidden' '
test_must_fail git tag -a &&
+ test_must_fail git tag -a -l &&
+ test_must_fail git tag -s &&
+ test_must_fail git tag -s -l &&
+ test_must_fail git tag -m &&
+ test_must_fail git tag -m -l &&
+ test_must_fail git tag -m "hlagh" &&
+ test_must_fail git tag -m "hlagh" -l &&
+ test_must_fail git tag -F &&
+ test_must_fail git tag -F -l &&
+ test_must_fail git tag -f &&
+ test_must_fail git tag -f -l &&
+ test_must_fail git tag -a -s -m -F &&
+ test_must_fail git tag -a -s -m -F -l &&
test_must_fail git tag -l -v &&
- test_must_fail git tag -n 100 &&
+ test_must_fail git tag -l -d &&
+ test_must_fail git tag -l -v -d &&
+ test_must_fail git tag -n 100 -v &&
test_must_fail git tag -l -m msg &&
test_must_fail git tag -l -F some file &&
- test_must_fail git tag -v -s
-'
+ test_must_fail git tag -v -s &&
+ test_must_fail git tag --contains tag-tree &&
+ test_must_fail git tag --contains tag-blob &&
+ test_must_fail git tag --no-contains tag-tree &&
+ test_must_fail git tag --no-contains tag-blob &&
+ test_must_fail git tag --contains --no-contains &&
+ test_must_fail git tag --no-with HEAD &&
+ test_must_fail git tag --no-without HEAD
+'
+
+for option in --contains --with --no-contains --without --merged --no-merged --points-at
+do
+ test_expect_success "mixing incompatible modes with $option is forbidden" "
+ test_must_fail git tag -d $option HEAD &&
+ test_must_fail git tag -d $option HEAD some-tag &&
+ test_must_fail git tag -v $option HEAD
+ "
+ test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" "
+ git tag -n $option HEAD HEAD &&
+ git tag $option HEAD HEAD &&
+ git tag $option
+ "
+done
# check points-at
-test_expect_success '--points-at cannot be used in non-list mode' '
- test_must_fail git tag --points-at=v4.0 foo
+test_expect_success '--points-at can be used in non-list mode' '
+ echo v4.0 >expect &&
+ git tag --points-at=v4.0 "v*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--points-at is a synonym for --points-at HEAD' '
+ echo v4.0 >expect &&
+ git tag --points-at >actual &&
+ test_cmp expect actual
'
test_expect_success '--points-at finds lightweight tags' '
test_lazy_prereq ULIMIT_STACK_SIZE 'run_with_limited_stack true'
# we require ulimit, this excludes Windows
-test_expect_success ULIMIT_STACK_SIZE '--contains works in a deep repo' '
+test_expect_success ULIMIT_STACK_SIZE '--contains and --no-contains work in a deep repo' '
>expect &&
i=1 &&
while test $i -lt 8000
git checkout master &&
git tag far-far-away HEAD^ &&
run_with_limited_stack git tag --contains HEAD >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+ run_with_limited_stack git tag --no-contains HEAD >actual &&
+ test_line_count ">" 10 actual
'
test_expect_success '--format should list tags as per format given' '
git tag mergetest-3 HEAD
'
-test_expect_success '--merged cannot be used in non-list mode' '
- test_must_fail git tag --merged=mergetest-2 foo
+test_expect_success '--merged can be used in non-list mode' '
+ cat >expect <<-\EOF &&
+ mergetest-1
+ mergetest-2
+ EOF
+ git tag --merged=mergetest-2 "mergetest*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--merged is incompatible with --no-merged' '
+ test_must_fail git tag --merged HEAD --no-merged HEAD
'
test_expect_success '--merged shows merged tags' '
test_cmp expect actual
'
+test_expect_success '--no-merged can be used in non-list mode' '
+ git tag --no-merged=mergetest-2 mergetest-* >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'ambiguous branch/tags not marked' '
git tag ambiguous &&
git branch ambiguous &&
test_cmp expect actual
'
+test_expect_success '--contains combined with --no-contains' '
+ (
+ git init no-contains &&
+ cd no-contains &&
+ test_commit v0.1 &&
+ test_commit v0.2 &&
+ test_commit v0.3 &&
+ test_commit v0.4 &&
+ test_commit v0.5 &&
+ cat >expected <<-\EOF &&
+ v0.2
+ v0.3
+ v0.4
+ EOF
+ git tag --contains v0.2 --no-contains v0.5 >actual &&
+ test_cmp expected actual
+ )
+'
+
+# As the docs say, list tags which contain a specified *commit*. We
+# don't recurse down to tags for trees or blobs pointed to by *those*
+# commits.
+test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
+ cd no-contains &&
+ blob=$(git rev-parse v0.3:v0.3.t) &&
+ tree=$(git rev-parse v0.3^{tree}) &&
+ git tag tag-blob $blob &&
+ git tag tag-tree $tree &&
+ git tag --contains v0.3 >actual &&
+ cat >expected <<-\EOF &&
+ v0.3
+ v0.4
+ v0.5
+ EOF
+ test_cmp expected actual &&
+ git tag --no-contains v0.3 >actual &&
+ cat >expected <<-\EOF &&
+ v0.1
+ v0.2
+ EOF
+ test_cmp expected actual
+'
+
test_done
)
}
+sanitize_output () {
+ sed -e "s/$_x40/HASH/" -e "s/$_x40/HASH/" output >output2 &&
+ mv output2 output
+}
+
+
test_expect_success 'setup' '
test_create_repo_with_commit sub &&
echo output > .gitignore &&
EOF
'
+test_expect_success 'status with modified file in submodule (short)' '
+ (cd sub && git reset --hard) &&
+ echo "changed" >sub/foo &&
+ git status --short >output &&
+ diff output - <<-\EOF
+ m sub
+ EOF
+'
+
test_expect_success 'status with added file in submodule' '
(cd sub && git reset --hard && echo >foo && git add foo) &&
git status >output &&
EOF
'
+test_expect_success 'status with added file in submodule (short)' '
+ (cd sub && git reset --hard && echo >foo && git add foo) &&
+ git status --short >output &&
+ diff output - <<-\EOF
+ m sub
+ EOF
+'
+
test_expect_success 'status with untracked file in submodule' '
(cd sub && git reset --hard) &&
echo "content" >sub/new-file &&
EOF
'
+test_expect_success 'status with untracked file in submodule (short)' '
+ git status --short >output &&
+ diff output - <<-\EOF
+ ? sub
+ EOF
+'
+
test_expect_success 'status with added and untracked file in submodule' '
(cd sub && git reset --hard && echo >foo && git add foo) &&
echo "content" >sub/new-file &&
test_i18ngrep "modified: sub (new commits, modified content)" output
'
+test_expect_success 'status with a lot of untracked files in the submodule' '
+ (
+ cd sub
+ i=0 &&
+ while test $i -lt 1024
+ do
+ >some-file-$i
+ i=$(( $i + 1 ))
+ done
+ ) &&
+ git status --porcelain sub 2>err.actual &&
+ test_must_be_empty err.actual &&
+ rm err.actual
+'
+
test_expect_success 'rm submodule contents' '
- rm -rf sub/* sub/.git
+ rm -rf sub &&
+ mkdir sub
'
test_expect_success 'status clean (empty submodule dir)' '
test_cmp diff_submodule_actual diff_submodule_expect
'
+# We'll setup different cases for further testing:
+# sub1 will contain a nested submodule,
+# sub2 will have an untracked file
+# sub3 will have an untracked repository
+test_expect_success 'setup superproject with untracked file in nested submodule' '
+ (
+ cd super &&
+ git clean -dfx &&
+ rm .gitmodules &&
+ git submodule add -f ./sub1 &&
+ git submodule add -f ./sub2 &&
+ git submodule add -f ./sub1 sub3 &&
+ git commit -a -m "messy merge in superproject" &&
+ (
+ cd sub1 &&
+ git submodule add ../sub2 &&
+ git commit -a -m "add sub2 to sub1"
+ ) &&
+ git add sub1 &&
+ git commit -a -m "update sub1 to contain nested sub"
+ ) &&
+ echo content >super/sub1/sub2/file &&
+ echo content >super/sub2/file &&
+ git -C super/sub3 clone ../../sub2 untracked_repository
+'
+
+test_expect_success 'status with untracked file in nested submodule (porcelain)' '
+ git -C super status --porcelain >output &&
+ diff output - <<-\EOF
+ M sub1
+ M sub2
+ M sub3
+ EOF
+'
+
+test_expect_success 'status with untracked file in nested submodule (porcelain=2)' '
+ git -C super status --porcelain=2 >output &&
+ sanitize_output output &&
+ diff output - <<-\EOF
+ 1 .M S..U 160000 160000 160000 HASH HASH sub1
+ 1 .M S..U 160000 160000 160000 HASH HASH sub2
+ 1 .M S..U 160000 160000 160000 HASH HASH sub3
+ EOF
+'
+
+test_expect_success 'status with untracked file in nested submodule (short)' '
+ git -C super status --short >output &&
+ diff output - <<-\EOF
+ ? sub1
+ ? sub2
+ ? sub3
+ EOF
+'
+
+test_expect_success 'setup superproject with modified file in nested submodule' '
+ git -C super/sub1/sub2 add file &&
+ git -C super/sub2 add file
+'
+
+test_expect_success 'status with added file in nested submodule (porcelain)' '
+ git -C super status --porcelain >output &&
+ diff output - <<-\EOF
+ M sub1
+ M sub2
+ M sub3
+ EOF
+'
+
+test_expect_success 'status with added file in nested submodule (porcelain=2)' '
+ git -C super status --porcelain=2 >output &&
+ sanitize_output output &&
+ diff output - <<-\EOF
+ 1 .M S.M. 160000 160000 160000 HASH HASH sub1
+ 1 .M S.M. 160000 160000 160000 HASH HASH sub2
+ 1 .M S..U 160000 160000 160000 HASH HASH sub3
+ EOF
+'
+
+test_expect_success 'status with added file in nested submodule (short)' '
+ git -C super status --short >output &&
+ diff output - <<-\EOF
+ m sub1
+ m sub2
+ ? sub3
+ EOF
+'
+
test_done
git commit -m "modified both"
'
+test_expect_success 'difftool -d with growing paths' '
+ a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
+ git init growing &&
+ (
+ cd growing &&
+ echo "test -f \"\$2/b\"" | write_script .git/test-for-b.sh &&
+ one=$(printf 1 | git hash-object -w --stdin) &&
+ two=$(printf 2 | git hash-object -w --stdin) &&
+ git update-index --add \
+ --cacheinfo 100644,$one,$a --cacheinfo 100644,$two,b &&
+ tree1=$(git write-tree) &&
+ git update-index --add \
+ --cacheinfo 100644,$two,$a --cacheinfo 100644,$one,b &&
+ tree2=$(git write-tree) &&
+ git checkout -- $a &&
+ git difftool -d --extcmd .git/test-for-b.sh $tree1 $tree2
+ )
+'
+
run_dir_diff_test () {
test_expect_success "$1 --no-symlinks" "
symlinks=--no-symlinks &&
static void standard_options(struct transport *t)
{
char buf[16];
- int n;
int v = t->verbose;
set_helper_option(t, "progress", t->progress ? "true" : "false");
- n = snprintf(buf, sizeof(buf), "%d", v + 1);
- if (n >= sizeof(buf))
- die("impossibly large verbosity value");
+ xsnprintf(buf, sizeof(buf), "%d", v + 1);
set_helper_option(t, "verbosity", buf);
switch (t->family) {
struct child_process *conn;
int fd[2];
unsigned got_remote_heads : 1;
- struct sha1_array extra_have;
- struct sha1_array shallow;
+ struct oid_array extra_have;
+ struct oid_array shallow;
};
static int set_git_option(struct git_transport_options *opts,
static int measure_abbrev(const struct object_id *oid, int sofar)
{
- char hex[GIT_SHA1_HEXSZ + 1];
+ char hex[GIT_MAX_HEXSZ + 1];
int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV);
return (w < sofar) ? sofar : w;
TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
!is_bare_repository()) {
struct ref *ref = remote_refs;
- struct sha1_array commits = SHA1_ARRAY_INIT;
+ struct oid_array commits = OID_ARRAY_INIT;
for (; ref; ref = ref->next)
if (!is_null_oid(&ref->new_oid))
- sha1_array_append(&commits, ref->new_oid.hash);
+ oid_array_append(&commits,
+ &ref->new_oid);
if (!push_unpushed_submodules(&commits,
transport->remote,
refspec, refspec_nr,
transport->push_options,
pretend)) {
- sha1_array_clear(&commits);
+ oid_array_clear(&commits);
die("Failed to push all needed submodules!");
}
- sha1_array_clear(&commits);
+ oid_array_clear(&commits);
}
if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) ||
!pretend)) && !is_bare_repository()) {
struct ref *ref = remote_refs;
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
- struct sha1_array commits = SHA1_ARRAY_INIT;
+ struct oid_array commits = OID_ARRAY_INIT;
for (; ref; ref = ref->next)
if (!is_null_oid(&ref->new_oid))
- sha1_array_append(&commits, ref->new_oid.hash);
+ oid_array_append(&commits,
+ &ref->new_oid);
if (find_unpushed_submodules(&commits, transport->remote->name,
&needs_pushing)) {
- sha1_array_clear(&commits);
+ oid_array_clear(&commits);
die_with_unpushed_submodules(&needs_pushing);
}
string_list_clear(&needs_pushing, 0);
- sha1_array_clear(&commits);
+ oid_array_clear(&commits);
}
if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY))
msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
_("The following working tree files would be removed by sparse checkout update:\n%s");
msgs[ERROR_WOULD_LOSE_SUBMODULE] =
- _("Submodule '%s' cannot checkout new HEAD");
+ _("Cannot update submodule:\n%s");
opts->show_all_errors = 1;
/* rejected paths may not have a static buffer */
strbuf_release(&twobuf);
}
+static char short_submodule_status(struct wt_status_change_data *d) {
+ if (d->new_submodule_commits)
+ return 'M';
+ if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
+ return 'm';
+ if (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
+ return '?';
+ return d->worktree_status;
+}
+
static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
struct diff_options *options,
void *data)
}
if (!d->worktree_status)
d->worktree_status = p->status;
- d->dirty_submodule = p->two->dirty_submodule;
- if (S_ISGITLINK(p->two->mode))
+ if (S_ISGITLINK(p->two->mode)) {
+ d->dirty_submodule = p->two->dirty_submodule;
d->new_submodule_commits = !!oidcmp(&p->one->oid,
&p->two->oid);
+ if (s->status_format == STATUS_FORMAT_SHORT)
+ d->worktree_status = short_submodule_status(d);
+ }
switch (p->status) {
case DIFF_STATUS_ADDED:
int hints;
enum wt_status_format status_format;
- unsigned char sha1_commit[GIT_SHA1_RAWSZ]; /* when not Initial */
+ unsigned char sha1_commit[GIT_MAX_RAWSZ]; /* when not Initial */
/* These are computed during processing of the individual sections */
int commitable;