#include "commit-slab.h"
#include "revision.h"
#include "list-objects.h"
+#include "commit-slab.h"
static int is_shallow = -1;
static struct stat_validity shallow_stat;
void set_alternate_shallow_file(const char *path, int override)
{
if (is_shallow != -1)
- die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
+ BUG("is_repository_shallow must not be called before set_alternate_shallow_file");
if (alternate_shallow_file && !override)
return;
free(alternate_shallow_file);
return is_shallow;
}
+/*
+ * TODO: use "int" elemtype instead of "int *" when/if commit-slab
+ * supports a "valid" flag.
+ */
+define_commit_slab(commit_depth, int *);
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
int shallow_flag, int not_shallow_flag)
{
struct object_array stack = OBJECT_ARRAY_INIT;
struct commit *commit = NULL;
struct commit_graft *graft;
+ struct commit_depth depths;
+ init_commit_depth(&depths);
while (commit || i < heads->nr || stack.nr) {
struct commit_list *p;
if (!commit) {
if (i < heads->nr) {
+ int **depth_slot;
commit = (struct commit *)
deref_tag(heads->objects[i++].item, NULL, 0);
if (!commit || commit->object.type != OBJ_COMMIT) {
commit = NULL;
continue;
}
- if (!commit->util)
- commit->util = xmalloc(sizeof(int));
- *(int *)commit->util = 0;
+ depth_slot = commit_depth_at(&depths, commit);
+ if (!*depth_slot)
+ *depth_slot = xmalloc(sizeof(int));
+ **depth_slot = 0;
cur_depth = 0;
} else {
commit = (struct commit *)
object_array_pop(&stack);
- cur_depth = *(int *)commit->util;
+ cur_depth = **commit_depth_at(&depths, commit);
}
}
parse_commit_or_die(commit);
}
commit->object.flags |= not_shallow_flag;
for (p = commit->parents, commit = NULL; p; p = p->next) {
- if (!p->item->util) {
- int *pointer = xmalloc(sizeof(int));
- p->item->util = pointer;
- *pointer = cur_depth;
+ int **depth_slot = commit_depth_at(&depths, p->item);
+ if (!*depth_slot) {
+ *depth_slot = xmalloc(sizeof(int));
+ **depth_slot = cur_depth;
} else {
- int *pointer = p->item->util;
- if (cur_depth >= *pointer)
+ if (cur_depth >= **depth_slot)
continue;
- *pointer = cur_depth;
+ **depth_slot = cur_depth;
}
if (p->next)
add_object_array(&p->item->object,
NULL, &stack);
else {
commit = p->item;
- cur_depth = *(int *)commit->util;
+ cur_depth = **commit_depth_at(&depths, commit);
}
}
}
+ for (i = 0; i < depths.slab_count; i++) {
+ int j;
+
+ for (j = 0; j < depths.slab_size; j++)
+ free(depths.slab[i][j]);
+ }
+ clear_commit_depth(&depths);
return result;
}
die("revision walk setup failed");
traverse_commit_list(&revs, show_commit, NULL, ¬_shallow_list);
+ if (!not_shallow_list)
+ die("no commits selected for shallow requests");
+
/* Mark all reachable commits as NOT_SHALLOW */
for (p = not_shallow_list; p; p = p->next)
p->item->object.flags |= not_shallow_flag;
static void check_shallow_file_for_update(void)
{
if (is_shallow == -1)
- die("BUG: shallow must be initialized by now");
+ BUG("shallow must be initialized by now");
if (!stat_validity_check(&shallow_stat, git_path_shallow()))
die("shallow file has changed since we read it");
*/
void prune_shallow(int show_only)
{
- static struct lock_file shallow_lock;
+ struct lock_file shallow_lock = LOCK_INIT;
struct strbuf sb = STRBUF_INIT;
int fd;
void *p;
if (!info->pool_count || size > info->end - info->free) {
if (size > POOL_SIZE)
- die("BUG: pool size too small for %d in paint_alloc()",
+ BUG("pool size too small for %d in paint_alloc()",
size);
info->pool_count++;
REALLOC_ARRAY(info->pools, info->pool_count);
test_tick &&
commit=$(echo "$text" | git commit-tree $tree $parents) &&
eval "$name=$commit; export $name" &&
- echo $commit > .git/refs/heads/$branch &&
+ git update-ref "refs/heads/$branch" "$commit" &&
eval ${branch}TIP=$commit
}
case "$heads" in
*A*)
- echo $ATIP > .git/refs/heads/A;;
+ git update-ref refs/heads/A "$ATIP";;
esac &&
case "$heads" in *B*)
- echo $BTIP > .git/refs/heads/B;;
+ git update-ref refs/heads/B "$BTIP";;
esac &&
git symbolic-ref HEAD refs/heads/$(echo $heads \
| sed -e "s/^\(.\).*$/\1/") &&
cur=$(($cur+1))
done &&
add B1 $A1 &&
- echo $ATIP > .git/refs/heads/A &&
- echo $BTIP > .git/refs/heads/B &&
+ git update-ref refs/heads/A "$ATIP" &&
+ git update-ref refs/heads/B "$BTIP" &&
git symbolic-ref HEAD refs/heads/B
'
test_expect_success 'test lonely missing ref' '
(
cd client &&
- test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
- ) >/dev/null 2>error-m &&
+ test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy 2>../error-m
+ ) &&
test_i18ncmp expect-error error-m
'
test_expect_success 'test missing ref after existing' '
(
cd client &&
- test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
- ) >/dev/null 2>error-em &&
+ test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy 2>../error-em
+ ) &&
test_i18ncmp expect-error error-em
'
test_expect_success 'test missing ref before existing' '
(
cd client &&
- test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
- ) >/dev/null 2>error-me &&
+ test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A 2>../error-me
+ ) &&
test_i18ncmp expect-error error-me
'
test_cmp expected actual
'
+ test_expect_success 'clone shallow since selects no commits' '
+ test_create_repo shallow-since-the-future &&
+ (
+ cd shallow-since-the-future &&
+ GIT_COMMITTER_DATE="100000000 +0700" git commit --allow-empty -m one &&
+ GIT_COMMITTER_DATE="200000000 +0700" git commit --allow-empty -m two &&
+ GIT_COMMITTER_DATE="300000000 +0700" git commit --allow-empty -m three &&
+ test_must_fail git clone --shallow-since "900000000 +0700" "file://$(pwd)/." ../shallow111
+ )
+ '
+
test_expect_success 'shallow clone exclude tag two' '
test_create_repo shallow-exclude &&
(
)
'
+test_expect_success 'filtering by size' '
+ rm -rf server client &&
+ test_create_repo server &&
+ test_commit -C server one &&
+ test_config -C server uploadpack.allowfilter 1 &&
+
+ test_create_repo client &&
+ git -C client fetch-pack --filter=blob:limit=0 ../server HEAD &&
+
+ # Ensure that object is not inadvertently fetched
+ test_must_fail git -C client cat-file -e $(git hash-object server/one.t)
+'
+
+test_expect_success 'filtering by size has no effect if support for it is not advertised' '
+ rm -rf server client &&
+ test_create_repo server &&
+ test_commit -C server one &&
+
+ test_create_repo client &&
+ git -C client fetch-pack --filter=blob:limit=0 ../server HEAD 2> err &&
+
+ # Ensure that object is fetched
+ git -C client cat-file -e $(git hash-object server/one.t) &&
+
+ test_i18ngrep "filtering not recognized by server" err
+'
+
+fetch_filter_blob_limit_zero () {
+ SERVER="$1"
+ URL="$2"
+
+ rm -rf "$SERVER" client &&
+ test_create_repo "$SERVER" &&
+ test_commit -C "$SERVER" one &&
+ test_config -C "$SERVER" uploadpack.allowfilter 1 &&
+
+ git clone "$URL" client &&
+ test_config -C client extensions.partialclone origin &&
+
+ test_commit -C "$SERVER" two &&
+
+ git -C client fetch --filter=blob:limit=0 origin HEAD:somewhere &&
+
+ # Ensure that commit is fetched, but blob is not
+ test_config -C client extensions.partialclone "arbitrary string" &&
+ git -C client cat-file -e $(git -C "$SERVER" rev-parse two) &&
+ test_must_fail git -C client cat-file -e $(git hash-object "$SERVER/two.t")
+}
+
+test_expect_success 'fetch with --filter=blob:limit=0' '
+ fetch_filter_blob_limit_zero server server
+'
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'fetch with --filter=blob:limit=0 and HTTP' '
+ fetch_filter_blob_limit_zero "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server"
+'
+
+stop_httpd
+
+
test_done