예제 #1
0
파일: fsck.c 프로젝트: DoWonJin/git
int cmd_fsck(int argc, const char **argv, const char *prefix)
{
	int i;
	struct alternate_object_database *alt;

	/* fsck knows how to handle missing promisor objects */
	fetch_if_missing = 0;

	errors_found = 0;
	check_replace_refs = 0;

	argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);

	fsck_walk_options.walk = mark_object;
	fsck_obj_options.walk = mark_used;
	fsck_obj_options.error_func = fsck_error_func;
	if (check_strict)
		fsck_obj_options.strict = 1;

	if (show_progress == -1)
		show_progress = isatty(2);
	if (verbose)
		show_progress = 0;

	if (write_lost_and_found) {
		check_full = 1;
		include_reflogs = 0;
	}

	if (name_objects)
		fsck_walk_options.object_names =
			xcalloc(1, sizeof(struct decoration));

	git_config(fsck_config, NULL);

	fsck_head_link();
	if (connectivity_only) {
		for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
		for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
	} else {
		struct alternate_object_database *alt_odb_list;

		fsck_object_dir(get_object_directory());

		prepare_alt_odb(the_repository);
		alt_odb_list = the_repository->objects->alt_odb_list;
		for (alt = alt_odb_list; alt; alt = alt->next)
			fsck_object_dir(alt->path);

		if (check_full) {
			struct packed_git *p;
			uint32_t total = 0, count = 0;
			struct progress *progress = NULL;

			if (show_progress) {
				for (p = get_packed_git(the_repository); p;
				     p = p->next) {
					if (open_pack_index(p))
						continue;
					total += p->num_objects;
				}

				progress = start_progress(_("Checking objects"), total);
			}
			for (p = get_packed_git(the_repository); p;
			     p = p->next) {
				/* verify gives error messages itself */
				if (verify_pack(p, fsck_obj_buffer,
						progress, count))
					errors_found |= ERROR_PACK;
				count += p->num_objects;
			}
			stop_progress(&progress);
		}
	}

	for (i = 0; i < argc; i++) {
		const char *arg = argv[i];
		struct object_id oid;
		if (!get_oid(arg, &oid)) {
			struct object *obj = lookup_object(oid.hash);

			if (!obj || !(obj->flags & HAS_OBJ)) {
				if (is_promisor_object(&oid))
					continue;
				error("%s: object missing", oid_to_hex(&oid));
				errors_found |= ERROR_OBJECT;
				continue;
			}

			obj->flags |= USED;
			if (name_objects)
				add_decoration(fsck_walk_options.object_names,
					obj, xstrdup(arg));
			mark_object_reachable(obj);
			continue;
		}
		error("invalid parameter: expected sha1, got '%s'", arg);
		errors_found |= ERROR_OBJECT;
	}

	/*
	 * If we've not been given any explicit head information, do the
	 * default ones from .git/refs. We also consider the index file
	 * in this case (ie this implies --cache).
	 */
	if (!argc) {
		get_default_heads();
		keep_cache_objects = 1;
	}

	if (keep_cache_objects) {
		verify_index_checksum = 1;
		verify_ce_order = 1;
		read_cache();
		for (i = 0; i < active_nr; i++) {
			unsigned int mode;
			struct blob *blob;
			struct object *obj;

			mode = active_cache[i]->ce_mode;
			if (S_ISGITLINK(mode))
				continue;
			blob = lookup_blob(&active_cache[i]->oid);
			if (!blob)
				continue;
			obj = &blob->object;
			obj->flags |= USED;
			if (name_objects)
				add_decoration(fsck_walk_options.object_names,
					obj,
					xstrfmt(":%s", active_cache[i]->name));
			mark_object_reachable(obj);
		}
		if (active_cache_tree)
			fsck_cache_tree(active_cache_tree);
	}

	check_connectivity();
	return errors_found;
}
예제 #2
0
파일: fetch-pack.c 프로젝트: hashpling/git
/*
 * Mark recent commits available locally and reachable from a local ref as
 * COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
 * COMMON_REF (otherwise, we are not planning to participate in negotiation, and
 * thus do not need COMMON_REF marks).
 *
 * The cutoff time for recency is determined by this heuristic: it is the
 * earliest commit time of the objects in refs that are commits and that we know
 * the commit time of.
 */
static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
					 struct fetch_pack_args *args,
					 struct ref **refs)
{
	struct ref *ref;
	int old_save_commit_buffer = save_commit_buffer;
	timestamp_t cutoff = 0;
	struct oidset loose_oid_set = OIDSET_INIT;
	int use_oidset = 0;
	struct loose_object_iter iter = {&loose_oid_set, *refs};

	/* Enumerate all loose objects or know refs are not so many. */
	use_oidset = !for_each_loose_object(add_loose_objects_to_set,
					    &iter, 0);

	save_commit_buffer = 0;

	for (ref = *refs; ref; ref = ref->next) {
		struct object *o;
		unsigned int flags = OBJECT_INFO_QUICK;

		if (use_oidset &&
		    !oidset_contains(&loose_oid_set, &ref->old_oid)) {
			/*
			 * I know this does not exist in the loose form,
			 * so check if it exists in a non-loose form.
			 */
			flags |= OBJECT_INFO_IGNORE_LOOSE;
		}

		if (!has_object_file_with_flags(&ref->old_oid, flags))
			continue;
		o = parse_object(the_repository, &ref->old_oid);
		if (!o)
			continue;

		/* We already have it -- which may mean that we were
		 * in sync with the other side at some time after
		 * that (it is OK if we guess wrong here).
		 */
		if (o->type == OBJ_COMMIT) {
			struct commit *commit = (struct commit *)o;
			if (!cutoff || cutoff < commit->date)
				cutoff = commit->date;
		}
	}

	oidset_clear(&loose_oid_set);

	if (!args->deepen) {
		for_each_ref(mark_complete_oid, NULL);
		for_each_cached_alternate(NULL, mark_alternate_complete);
		commit_list_sort_by_date(&complete);
		if (cutoff)
			mark_recent_complete_commits(args, cutoff);
	}

	/*
	 * Mark all complete remote refs as common refs.
	 * Don't mark them common yet; the server has to be told so first.
	 */
	for (ref = *refs; ref; ref = ref->next) {
		struct object *o = deref_tag(the_repository,
					     lookup_object(the_repository,
					     ref->old_oid.hash),
					     NULL, 0);

		if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
			continue;

		negotiator->known_common(negotiator,
					 (struct commit *)o);
	}

	save_commit_buffer = old_save_commit_buffer;
}
예제 #3
0
파일: fetch-pack.c 프로젝트: DoWonJin/git
static int everything_local(struct fetch_pack_args *args,
			    struct ref **refs,
			    struct ref **sought, int nr_sought)
{
	struct ref *ref;
	int retval;
	int old_save_commit_buffer = save_commit_buffer;
	timestamp_t cutoff = 0;
	struct oidset loose_oid_set = OIDSET_INIT;
	int use_oidset = 0;
	struct loose_object_iter iter = {&loose_oid_set, *refs};

	/* Enumerate all loose objects or know refs are not so many. */
	use_oidset = !for_each_loose_object(add_loose_objects_to_set,
					    &iter, 0);

	save_commit_buffer = 0;

	for (ref = *refs; ref; ref = ref->next) {
		struct object *o;
		unsigned int flags = OBJECT_INFO_QUICK;

		if (use_oidset &&
		    !oidset_contains(&loose_oid_set, &ref->old_oid)) {
			/*
			 * I know this does not exist in the loose form,
			 * so check if it exists in a non-loose form.
			 */
			flags |= OBJECT_INFO_IGNORE_LOOSE;
		}

		if (!has_object_file_with_flags(&ref->old_oid, flags))
			continue;
		o = parse_object(&ref->old_oid);
		if (!o)
			continue;

		/* We already have it -- which may mean that we were
		 * in sync with the other side at some time after
		 * that (it is OK if we guess wrong here).
		 */
		if (o->type == OBJ_COMMIT) {
			struct commit *commit = (struct commit *)o;
			if (!cutoff || cutoff < commit->date)
				cutoff = commit->date;
		}
	}

	oidset_clear(&loose_oid_set);

	if (!args->no_dependents) {
		if (!args->deepen) {
			for_each_ref(mark_complete_oid, NULL);
			for_each_cached_alternate(mark_alternate_complete);
			commit_list_sort_by_date(&complete);
			if (cutoff)
				mark_recent_complete_commits(args, cutoff);
		}

		/*
		 * Mark all complete remote refs as common refs.
		 * Don't mark them common yet; the server has to be told so first.
		 */
		for (ref = *refs; ref; ref = ref->next) {
			struct object *o = deref_tag(lookup_object(ref->old_oid.hash),
						     NULL, 0);

			if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
				continue;

			if (!(o->flags & SEEN)) {
				rev_list_push((struct commit *)o, COMMON_REF | SEEN);

				mark_common((struct commit *)o, 1, 1);
			}
		}
	}

	filter_refs(args, refs, sought, nr_sought);

	for (retval = 1, ref = *refs; ref ; ref = ref->next) {
		const struct object_id *remote = &ref->old_oid;
		struct object *o;

		o = lookup_object(remote->hash);
		if (!o || !(o->flags & COMPLETE)) {
			retval = 0;
			print_verbose(args, "want %s (%s)", oid_to_hex(remote),
				      ref->name);
			continue;
		}
		print_verbose(args, _("already have %s (%s)"), oid_to_hex(remote),
			      ref->name);
	}

	save_commit_buffer = old_save_commit_buffer;

	return retval;
}