From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Subject: [PATCH 3/5] unpack-trees: move all skip-worktree checks back to unpack_trees() Date: Sat, 27 Nov 2010 01:17:45 +0700 Message-ID: <1290795467-7570-4-git-send-email-pclouds@gmail.com> References: <1290795467-7570-1-git-send-email-pclouds@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= To: Junio C Hamano , git@vger.kernel.org, Jonathan Niedier , tfransosi@gmail.com X-From: git-owner@vger.kernel.org Fri Nov 26 19:19:33 2010 Return-path: Envelope-to: gcvg-git-2@lo.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1PM2tR-0003MS-4H for gcvg-git-2@lo.gmane.org; Fri, 26 Nov 2010 19:19:33 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755400Ab0KZST0 convert rfc822-to-quoted-printable (ORCPT ); Fri, 26 Nov 2010 13:19:26 -0500 Received: from mail-pv0-f194.google.com ([74.125.83.194]:40259 "EHLO mail-pv0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751027Ab0KZSTZ (ORCPT ); Fri, 26 Nov 2010 13:19:25 -0500 Received: by pva18 with SMTP id 18so480774pva.1 for ; Fri, 26 Nov 2010 10:19:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:from:to:cc:subject :date:message-id:x-mailer:in-reply-to:references:mime-version :content-type:content-transfer-encoding; bh=E97KLV5tVeuu8WP9aJinNp4QqhlzmNL3h0PTfXUcQOQ=; b=mUnlGn2ULxEhrAq+ggbl+2UEiy2qkMa728cJG6EmzLq/blghnl23eXmEPd0okRbLAd JZbcuS4LAwzX7ojKPmb2GAVHpqcjl489m5uxr5637bhKmlquLhay0acu8hFgqPZXiBEU vkYqTj75pSzM8m6rv++9NHl70WGTi5UFBoTuc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding; b=OysIWcZrrIX1MzsgcXnEj5SMnv42K/Xds4kdivvlGy+vWO+8lm2JNNFYheQKHX9rI/ YZSqz8InAsPCrN6NODAY6f8V7bwtdPOfi2zjfkr7sJqLo7Jl/SPrEQDBXfmVQou/FBJH VnyNKPaskVfz48h47nRvVCX67W+WO85HlPaB8= Received: by 10.142.44.7 with SMTP id r7mr2788638wfr.114.1290795565102; Fri, 26 Nov 2010 10:19:25 -0800 (PST) Received: from pclouds@gmail.com ([115.73.252.168]) by mx.google.com with ESMTPS id y42sm2857154wfd.22.2010.11.26.10.19.20 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 26 Nov 2010 10:19:24 -0800 (PST) Received: by pclouds@gmail.com (sSMTP sendmail emulation); Sat, 27 Nov 2010 01:18:22 +0700 X-Mailer: git-send-email 1.7.3.2.316.gda8b3 In-Reply-To: <1290795467-7570-1-git-send-email-pclouds@gmail.com> Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: Earlier, the will_have_skip_worktree() checks are done in various places, which makes it hard to traverse the index tree-alike, required by excluded_from_list(). This patch moves all the checks into two loops in unpack_trees(). Entries in index in this operation can be classified into two groups: ones already in index before unpack_trees() is called and ones added to index after traverse_trees() is called. In both groups, before checking file status on worktree, the future skip-worktree bit must be checked, so that if an entry will be outside worktree, worktree should not be checked. =46or the first group, the future skip-worktree bit is precomputed and stored as CE_NEW_SKIP_WORKTREE in the first loop before traverse_trees() is called so that *way_merge() function does not need to compute it again. =46or the second group, because we don't know what entries will be in this group until traverse_trees() finishes, operations that need future skip-worktree check is delayed until CE_NEW_SKIP_WORKTREE is computed in the second loop. CE_ADDED is used to mark entries in the second group. CE_ADDED and CE_NEW_SKIP_WORKTREE are temporary flags used in unpack_trees(). CE_ADDED is only used by add_to_index(), which should not be called while unpack_trees() is running. Signed-off-by: Nguy=E1=BB=85n Th=C3=A1i Ng=E1=BB=8Dc Duy --- cache.h | 1 + unpack-trees.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++= +------ 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/cache.h b/cache.h index 4819cf5..52b998b 100644 --- a/cache.h +++ b/cache.h @@ -181,6 +181,7 @@ struct cache_entry { #define CE_CONFLICTED 0x800000 =20 #define CE_UNPACKED 0x1000000 +#define CE_NEW_SKIP_WORKTREE 0x2000000 =20 /* * Extended on-disk flags diff --git a/unpack-trees.c b/unpack-trees.c index 4d92412..a6518db 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -258,7 +258,7 @@ static int apply_sparse_checkout(struct cache_entry= *ce, struct unpack_trees_opt { int was_skip_worktree =3D ce_skip_worktree(ce); =20 - if (!ce_stage(ce) && will_have_skip_worktree(ce, o)) + if (ce->ce_flags & CE_NEW_SKIP_WORKTREE) ce->ce_flags |=3D CE_SKIP_WORKTREE; else ce->ce_flags &=3D ~CE_SKIP_WORKTREE; @@ -333,7 +333,7 @@ static void mark_all_ce_unused(struct index_state *= index) { int i; for (i =3D 0; i < index->cache_nr; i++) - index->cache[i]->ce_flags &=3D ~CE_UNPACKED; + index->cache[i]->ce_flags &=3D ~(CE_UNPACKED | CE_ADDED | CE_NEW_SKI= P_WORKTREE); } =20 static int locate_in_src_index(struct cache_entry *ce, @@ -835,8 +835,33 @@ static int unpack_callback(int n, unsigned long ma= sk, unsigned long dirmask, str } =20 /* + * Set/Clear CE_NEW_SKIP_WORKTREE according to $GIT_DIR/info/sparse-ch= eckout + */ +static void mark_new_skip_worktree(struct exclude_list *el, + struct index_state *the_index, + int select_flag, int skip_wt_flag) +{ + int i; + + for (i =3D 0; i < the_index->cache_nr; i++) { + struct cache_entry *ce =3D the_index->cache[i]; + + if (select_flag && !(ce->ce_flags & select_flag)) + continue; + + if (!ce_stage(ce) && will_have_skip_worktree(ce, o)) + ce->ce_flags |=3D skip_wt_flag; + else + ce->ce_flags &=3D ~skip_wt_flag; + } +} + +static int verify_absent(struct cache_entry *, enum unpack_trees_error= _types, struct unpack_trees_options *); +/* * N-way merge "len" trees. Returns 0 on success, -1 on failure to ma= nipulate the * resulting index, -2 on failure to reflect the changes to the work t= ree. + * + * CE_ADDED, CE_UNPACKED and CE_NEW_SKIP_WORKTREE are used internally */ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_tree= s_options *o) { @@ -869,6 +894,12 @@ int unpack_trees(unsigned len, struct tree_desc *t= , struct unpack_trees_options o->merge_size =3D len; mark_all_ce_unused(o->src_index); =20 + /* + * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries + */ + if (!o->skip_sparse_checkout) + mark_new_skip_worktree(o->el, o->src_index, 0, CE_NEW_SKIP_WORKTREE)= ; + if (!dfc) dfc =3D xcalloc(1, cache_entry_size(0)); o->df_conflict_entry =3D dfc; @@ -922,9 +953,29 @@ int unpack_trees(unsigned len, struct tree_desc *t= , struct unpack_trees_options =20 if (!o->skip_sparse_checkout) { int empty_worktree =3D 1; - for (i =3D 0;i < o->result.cache_nr;i++) { + + /* + * Sparse checkout loop #2: set NEW_SKIP_WORKTREE on entries not in = loop #1 + * If the will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE + * so apply_sparse_checkout() won't attempt to remove it from worktr= ee + */ + mark_new_skip_worktree(o->el, &o->result, CE_ADDED, CE_SKIP_WORKTREE= | CE_NEW_SKIP_WORKTREE); + + for (i =3D 0; i < o->result.cache_nr; i++) { struct cache_entry *ce =3D o->result.cache[i]; =20 + /* + * Entries marked with CE_ADDED in merged_entry() do not have + * verify_absent() check (the check is effectively disabled + * because CE_NEW_SKIP_WORKTREE is set unconditionally). + * + * Do the real check now because we have had + * correct CE_NEW_SKIP_WORKTREE + */ + if (ce->ce_flags & CE_ADDED && + verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) + return -1; + if (apply_sparse_checkout(ce, o)) { ret =3D -1; goto done; @@ -1013,7 +1064,7 @@ static int verify_uptodate_1(struct cache_entry *= ce, static int verify_uptodate(struct cache_entry *ce, struct unpack_trees_options *o) { - if (!o->skip_sparse_checkout && will_have_skip_worktree(ce, o)) + if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE)= ) return 0; return verify_uptodate_1(ce, o, ERROR_NOT_UPTODATE_FILE); } @@ -1200,7 +1251,7 @@ static int verify_absent(struct cache_entry *ce, enum unpack_trees_error_types error_type, struct unpack_trees_options *o) { - if (!o->skip_sparse_checkout && will_have_skip_worktree(ce, o)) + if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE)= ) return 0; return verify_absent_1(ce, error_type, o); } @@ -1222,10 +1273,23 @@ static int merged_entry(struct cache_entry *mer= ge, struct cache_entry *old, int update =3D CE_UPDATE; =20 if (!old) { + /* + * New index entries. In sparse checkout, the following + * verify_absent() will be delayed until after + * traverse_trees() finishes in unpack_trees(), then: + * + * - CE_NEW_SKIP_WORKTREE will be computed correctly + * - verify_absent() be called again, this time with + * correct CE_NEW_SKIP_WORKTREE + * + * verify_absent() call here does nothing in sparse + * checkout (i.e. o->skip_sparse_checkout =3D=3D 0) + */ + update |=3D CE_ADDED; + merge->ce_flags |=3D CE_NEW_SKIP_WORKTREE; + if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) return -1; - if (!o->skip_sparse_checkout && will_have_skip_worktree(merge, o)) - update |=3D CE_SKIP_WORKTREE; invalidate_ce_path(merge, o); } else if (!(old->ce_flags & CE_CONFLICTED)) { /* @@ -1241,8 +1305,8 @@ static int merged_entry(struct cache_entry *merge= , struct cache_entry *old, } else { if (verify_uptodate(old, o)) return -1; - if (ce_skip_worktree(old)) - update |=3D CE_SKIP_WORKTREE; + /* Migrate old flags over */ + update |=3D old->ce_flags & (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTRE= E); invalidate_ce_path(old, o); } } else { --=20 1.7.3.2.316.gda8b3