From patchwork Tue Jun 18 23:27:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003107 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2762A1395 for ; Tue, 18 Jun 2019 23:28:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 167DA28901 for ; Tue, 18 Jun 2019 23:28:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 09E2C28ACA; Tue, 18 Jun 2019 23:28:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53FED28901 for ; Tue, 18 Jun 2019 23:28:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726543AbfFRX2r (ORCPT ); Tue, 18 Jun 2019 19:28:47 -0400 Received: from mail-qk1-f195.google.com ([209.85.222.195]:41739 "EHLO mail-qk1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX2r (ORCPT ); Tue, 18 Jun 2019 19:28:47 -0400 Received: by mail-qk1-f195.google.com with SMTP id c11so9751145qkk.8 for ; Tue, 18 Jun 2019 16:28:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rjlzvVO1JPURsSOsBfUZv8t0EuqI/VEQjnMH7ttmKVc=; b=E0Mdz7UW18ZJ48JxAvwtJp4NG371Ge8QjRCB5ABxZ6yfG4BthuvUXJABE/PMTHHtPl 6yHgSrIq626ygJrJzEdjpyeIx8U5zeKuOE5l3dwdSAG+C5Y7R89esVMAMZfpXr0hSRI4 fO+qDiozKkRkshM4MaRRkxmJyoEG4glrumphVVMRfaR5Ej+ZRjfoDoEQDClvScmjbcQW vn15OxsXLv2P/7Dwe3oP7VRUtUlZ/QsTF0NiDql/Wjef+GS8XfZip6uOVTD2Z/95k3YS SsOyLWJJlJj0X5wBKk5GUglXFJmxu2pN+VuJ/7mD45A10mTV5yZpL9BV2ce4lfY0m3iY MI9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rjlzvVO1JPURsSOsBfUZv8t0EuqI/VEQjnMH7ttmKVc=; b=k71/D1fK/u/ii9ylySBqpHNgDftcFYORRz1kMYINd/o1ldgbJqPFfJIwq6P4NKsXfb /nf5R7a2hK7+KNAr7AXuU4+z2PH80rf1Zl8yT3CJ+P5ig96bkgLNVpDdkJ3c+0ST6+/8 7jmWeFKLbWqtPjMzpo12N87qriF+HAEQDmrjOj2miT717Nbw12pbQr52ZGOtFCDOVbDv Gs3ALJQHye7Gd9+zbBVCO680ciG9zKzfQ8QGg8yVy4jSzcyPtoXDNU6R3jxAyDVWqLj3 O9XeFKijiON60NOqeMuU6VwGaOjQaYBsOtgEFAmxgyp/HmNa+f+dwYnEgvIaLwZYzNIm VNhQ== X-Gm-Message-State: APjAAAXz1PD1iUwJbxEj7E5SweblUANi73sTCWLOTfIVQ0CSV6HKVJ1f AHCaEtiB+QoJ1IQHFvjSvS9qbCwdweU= X-Google-Smtp-Source: APXvYqwRGvJXNVW9tcFRMyRaV7Pse7DfBit83htjG+OOK+Uh85wY3V+FsCdRGaHsf2yBz7AE13po8A== X-Received: by 2002:a37:9ece:: with SMTP id h197mr77790958qke.50.1560900525500; Tue, 18 Jun 2019 16:28:45 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.28.42 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:28:44 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Alex Riesen , Junio C Hamano Subject: [GSoC][PATCH v7 01/10] clone: test for our behavior on odd objects/* content Date: Tue, 18 Jun 2019 20:27:38 -0300 Message-Id: <17c0ba24062a61eb7b3a03dc4d5630a64db1e9f9.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ævar Arnfjörð Bjarmason Add tests for what happens when we perform a local clone on a repo containing odd files at .git/object directory, such as symlinks to other dirs, or unknown files. I'm bending over backwards here to avoid a SHA-1 dependency. See [1] for an earlier and simpler version that hardcoded SHA-1s. This behavior has been the same for a *long* time, but hasn't been tested for. There's a good post-hoc argument to be made for copying over unknown things, e.g. I'd like a git version that doesn't know about the commit-graph to copy it under "clone --local" so a newer git version can make use of it. In follow-up commits we'll look at changing some of this behavior, but for now, let's just assert it as-is so we'll notice what we'll change later. 1. https://public-inbox.org/git/20190226002625.13022-5-avarab@gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason [matheus.bernardino: improved and split tests in more than one patch] Helped-by: Matheus Tavares Signed-off-by: Matheus Tavares --- t/t5604-clone-reference.sh | 111 +++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 4320082b1b..207650cb95 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -221,4 +221,115 @@ test_expect_success 'clone, dissociate from alternates' ' ( cd C && git fsck ) ' +test_expect_success 'setup repo with garbage in objects/*' ' + git init S && + ( + cd S && + test_commit A && + + cd .git/objects && + >.some-hidden-file && + >some-file && + mkdir .some-hidden-dir && + >.some-hidden-dir/some-file && + >.some-hidden-dir/.some-dot-file && + mkdir some-dir && + >some-dir/some-file && + >some-dir/.some-dot-file + ) +' + +test_expect_success 'clone a repo with garbage in objects/*' ' + for option in --local --no-hardlinks --shared --dissociate + do + git clone $option S S$option || return 1 && + git -C S$option fsck || return 1 + done && + find S-* -name "*some*" | sort >actual && + cat >expected <<-EOF && + S--dissociate/.git/objects/.some-hidden-file + S--dissociate/.git/objects/some-dir + S--dissociate/.git/objects/some-dir/.some-dot-file + S--dissociate/.git/objects/some-dir/some-file + S--dissociate/.git/objects/some-file + S--local/.git/objects/.some-hidden-file + S--local/.git/objects/some-dir + S--local/.git/objects/some-dir/.some-dot-file + S--local/.git/objects/some-dir/some-file + S--local/.git/objects/some-file + S--no-hardlinks/.git/objects/.some-hidden-file + S--no-hardlinks/.git/objects/some-dir + S--no-hardlinks/.git/objects/some-dir/.some-dot-file + S--no-hardlinks/.git/objects/some-dir/some-file + S--no-hardlinks/.git/objects/some-file + EOF + test_cmp expected actual +' + +test_expect_success SYMLINKS 'setup repo with manually symlinked dirs and unknown files at objects/' ' + git init T && + ( + cd T && + git config gc.auto 0 && + test_commit A && + git gc && + test_commit B && + + cd .git/objects && + mv pack packs && + ln -s packs pack && + find ?? -type d >loose-dirs && + last_loose=$(tail -n 1 loose-dirs) && + rm -f loose-dirs && + mv $last_loose a-loose-dir && + ln -s a-loose-dir $last_loose && + find . -type f | sort >../../../T.objects-files.raw && + echo unknown_content> unknown_file + ) && + git -C T fsck && + git -C T rev-list --all --objects >T.objects +' + + +test_expect_success SYMLINKS 'clone repo with symlinked dirs and unknown files at objects/' ' + for option in --local --no-hardlinks --shared --dissociate + do + git clone $option T T$option || return 1 && + git -C T$option fsck || return 1 && + git -C T$option rev-list --all --objects >T$option.objects && + test_cmp T.objects T$option.objects && + ( + cd T$option/.git/objects && + find . -type f | sort >../../../T$option.objects-files.raw + ) + done && + + for raw in $(ls T*.raw) + do + sed -e "s!/../!/Y/!; s![0-9a-f]\{38,\}!Z!" -e "/commit-graph/d" \ + -e "/multi-pack-index/d" <$raw >$raw.de-sha || return 1 + done && + + cat >expected-files <<-EOF && + ./Y/Z + ./Y/Z + ./a-loose-dir/Z + ./Y/Z + ./info/packs + ./pack/pack-Z.idx + ./pack/pack-Z.pack + ./packs/pack-Z.idx + ./packs/pack-Z.pack + ./unknown_file + EOF + + for option in --local --dissociate --no-hardlinks + do + test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 + done && + + echo ./info/alternates >expected-files && + test_cmp expected-files T--shared.objects-files.raw +' + test_done From patchwork Tue Jun 18 23:27:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003109 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D9F2814B6 for ; Tue, 18 Jun 2019 23:28:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CA2ED28901 for ; Tue, 18 Jun 2019 23:28:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BE56828ACA; Tue, 18 Jun 2019 23:28:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 31E2428901 for ; Tue, 18 Jun 2019 23:28:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726739AbfFRX24 (ORCPT ); Tue, 18 Jun 2019 19:28:56 -0400 Received: from mail-qt1-f195.google.com ([209.85.160.195]:35105 "EHLO mail-qt1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX24 (ORCPT ); Tue, 18 Jun 2019 19:28:56 -0400 Received: by mail-qt1-f195.google.com with SMTP id d23so17702684qto.2 for ; Tue, 18 Jun 2019 16:28:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HZeQvGDF6ph32VZaJg9CsEtLW+IEjcr2kE9QW8pbBAQ=; b=dEFtLtPkD7PAMvsz4GQOVDyWmz99+nZ26txnEItLxBv1ov92TP0j+ZAodvXJ4xUuDA ee/HSKenl9OFLsjMbhE+TXxTzOKEX4wI+/QYPWTqQiGs0nB0WG2xLdIJ4be2YIINFoVg 494FhHR56MWn4xmiUspgQzX7cOZZg1MlPZV2Xd5R7XGq8zlXcYKIoIw2kLy0t5EujSmz x0wi9uzXFJWfA+idxLpk1dcxQgQAS8RBsHYx0cBOF+En+ZlZqYS9+OFRZwZgCX5ucxK6 jESt5tc3m7+x87PR27MgB9t4bN7Y2yikBEWrep3Kjhz3nx4uEgWTDXZ9aZKq2zA1aTPd 0qSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HZeQvGDF6ph32VZaJg9CsEtLW+IEjcr2kE9QW8pbBAQ=; b=ek6Diof9bxv7vQNOStr2P0+oiibYlTSZvEMvBnpNz5HLFhEQt9QG2iGqyVX1kmtWeu yZUxDGrff+I71FO+LJTr/dQrpMt+1Ric+ddn+anJeCJ0Tzt3tdvESQhoPQ4OfZqAh7SL v72DxeV324aLpYhVAVw90abd17H59AydAV5XFXysfloft0DVixJhu2NC4aVWVdyQkh1W AUSptlqmfwW56VFrc3z+5BsTxNsss4zBoJJmBFpdTQJuNMx2kIzMxhPofpiJvIshUmsj ARGsddZ9FMPy5E3mThk04gEVDi8FOEHTki7RSa7Ji2mIsW/FrTREfy4qRyVsIDj2KxZ1 c3Eg== X-Gm-Message-State: APjAAAVjjlZjZB4tQTCkAAdiHxHL3yFMQo7w5mhpnN54uTg1QRM03z4R L8yq26JHBm//Roy4nEps6Ej37azx6t4= X-Google-Smtp-Source: APXvYqw+SAwMxE3e3IIZtPr42Y6AxpxUuLhUUzc/XxuIUKKW8ABsJg0HnLhD8RLeE7IrzPjwDijoGQ== X-Received: by 2002:ac8:c0e:: with SMTP id k14mr59679514qti.72.1560900534757; Tue, 18 Jun 2019 16:28:54 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.28.51 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:28:54 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Junio C Hamano , Jeff King Subject: [GSoC][PATCH v7 02/10] clone: better handle symlinked files at .git/objects/ Date: Tue, 18 Jun 2019 20:27:39 -0300 Message-Id: <722350fe00de73d28df1a9c8667c84171aa8c1f5.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There is currently an odd behaviour when locally cloning a repository with symlinks at .git/objects: using --no-hardlinks all symlinks are dereferenced but without it, Git will try to hardlink the files with the link() function, which has an OS-specific behaviour on symlinks. On OSX and NetBSD, it creates a hardlink to the file pointed by the symlink whilst on GNU/Linux, it creates a hardlink to the symlink itself. On Manjaro GNU/Linux: $ touch a $ ln -s a b $ link b c $ ls -li a b c 155 [...] a 156 [...] b -> a 156 [...] c -> a But on NetBSD: $ ls -li a b c 2609160 [...] a 2609164 [...] b -> a 2609160 [...] c It's not good to have the result of a local clone to be OS-dependent and besides that, the current behaviour on GNU/Linux may result in broken symlinks. So let's standardize this by making the hardlinks always point to dereferenced paths, instead of the symlinks themselves. Also, add tests for symlinked files at .git/objects/. Note: Git won't create symlinks at .git/objects itself, but it's better to handle this case and be friendly with users who manually create them. Signed-off-by: Matheus Tavares Signed-off-by: Ævar Arnfjörð Bjarmason Co-authored-by: Ævar Arnfjörð Bjarmason --- builtin/clone.c | 2 +- t/t5604-clone-reference.sh | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 5b9ebe9947..4a0a2455a7 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -445,7 +445,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, if (unlink(dest->buf) && errno != ENOENT) die_errno(_("failed to unlink '%s'"), dest->buf); if (!option_no_hardlinks) { - if (!link(src->buf, dest->buf)) + if (!link(real_path(src->buf), dest->buf)) continue; if (option_local > 0) die_errno(_("failed to create link '%s'"), dest->buf); diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 207650cb95..0800c3853f 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -266,7 +266,7 @@ test_expect_success 'clone a repo with garbage in objects/*' ' test_cmp expected actual ' -test_expect_success SYMLINKS 'setup repo with manually symlinked dirs and unknown files at objects/' ' +test_expect_success SYMLINKS 'setup repo with manually symlinked or unknown files at objects/' ' git init T && ( cd T && @@ -280,10 +280,19 @@ test_expect_success SYMLINKS 'setup repo with manually symlinked dirs and unknow ln -s packs pack && find ?? -type d >loose-dirs && last_loose=$(tail -n 1 loose-dirs) && - rm -f loose-dirs && mv $last_loose a-loose-dir && ln -s a-loose-dir $last_loose && + first_loose=$(head -n 1 loose-dirs) && + rm -f loose-dirs && + + cd $first_loose && + obj=$(ls *) && + mv $obj ../an-object && + ln -s ../an-object $obj && + + cd ../ && find . -type f | sort >../../../T.objects-files.raw && + find . -type l | sort >../../../T.objects-symlinks.raw && echo unknown_content> unknown_file ) && git -C T fsck && @@ -291,7 +300,7 @@ test_expect_success SYMLINKS 'setup repo with manually symlinked dirs and unknow ' -test_expect_success SYMLINKS 'clone repo with symlinked dirs and unknown files at objects/' ' +test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at objects/' ' for option in --local --no-hardlinks --shared --dissociate do git clone $option T T$option || return 1 && @@ -300,7 +309,8 @@ test_expect_success SYMLINKS 'clone repo with symlinked dirs and unknown files a test_cmp T.objects T$option.objects && ( cd T$option/.git/objects && - find . -type f | sort >../../../T$option.objects-files.raw + find . -type f | sort >../../../T$option.objects-files.raw && + find . -type l | sort >../../../T$option.objects-symlinks.raw ) done && @@ -314,6 +324,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked dirs and unknown files a ./Y/Z ./Y/Z ./a-loose-dir/Z + ./an-object ./Y/Z ./info/packs ./pack/pack-Z.idx @@ -323,13 +334,15 @@ test_expect_success SYMLINKS 'clone repo with symlinked dirs and unknown files a ./unknown_file EOF - for option in --local --dissociate --no-hardlinks + for option in --local --no-hardlinks --dissociate do - test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 + test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 && + test_must_be_empty T$option.objects-symlinks.raw.de-sha || return 1 done && echo ./info/alternates >expected-files && - test_cmp expected-files T--shared.objects-files.raw + test_cmp expected-files T--shared.objects-files.raw && + test_must_be_empty T--shared.objects-symlinks.raw ' test_done From patchwork Tue Jun 18 23:27:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003111 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 349C114B6 for ; Tue, 18 Jun 2019 23:29:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23A9F28901 for ; Tue, 18 Jun 2019 23:29:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17CE628ACA; Tue, 18 Jun 2019 23:29:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8BBF028901 for ; Tue, 18 Jun 2019 23:29:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728881AbfFRX3D (ORCPT ); Tue, 18 Jun 2019 19:29:03 -0400 Received: from mail-qk1-f194.google.com ([209.85.222.194]:34090 "EHLO mail-qk1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3D (ORCPT ); Tue, 18 Jun 2019 19:29:03 -0400 Received: by mail-qk1-f194.google.com with SMTP id t8so9771725qkt.1 for ; Tue, 18 Jun 2019 16:29:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hwF3tfzYDWjFlaGtHtkNWoMVZECCkGQuNX+SZav6ClE=; b=dGAvxey4CPng/IgxifZ3bAChAAMLeNAQi0NOZ3qaJ6C//ZFeF5gjMN2xtqGP4BrCkZ j1PAcoLeRsOTepoA6Zqbj4JPKEgdQGAnpQVBI2sLNAPQU/7t1WF7L5nf1XmrRuq/v8qR L8yQEhMSMn0+get14dhiVaDCtQ+uTVnHXK5WLOUSJzcoFAaj1YUx3oewF5bKMKkdvzu/ 07MZuaHG6t0wLe9dL06XaAvyVBXBgkyeKrTB4T1fjUDqLmj6b0Fn/bSGokP2XJbcnY8O rmdYAM/rV1skBtDvk2+14f/dVOL0qKPGgL+NqD3GhT2FYL3MKThIDIXSoZcsrsICevrA iC8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hwF3tfzYDWjFlaGtHtkNWoMVZECCkGQuNX+SZav6ClE=; b=q0sb9xZXjhr/iW9px/SSXVj0kxUJWRY288a9rUrvpvnDtec7qnGuZUi4wdMawyC2ef wo835/ux2VE0uQSVlK3xCKJ9qjbnFkOVSVnc1QL+eCMICIsd2ZdHcK4sU/ZeyOv10VuR VwCrF/76l9Nw3uD3nHJQjRFPLvjEUjg8gU3l5N4WsU7I7hnssfx1nufqTrqycOkz+G40 Kad79PgX0uZDF9tj46zH71s5dOrbAgOgLZ+Zic04RlcjBvySGaf2VQlMVNVvalMTssx1 L2aLF7bhBPfk66ZOPEzWHgm5RqTb+WgJVW0jN09xoNOQn0VtWjZZSD0T9yYDXfL2V79A zg7w== X-Gm-Message-State: APjAAAW5tW7LFYxaNB7CcvV4PC2xw/DmmdSawrnRhhlQHPcZMA19ySzL MMCGZvs21oeaq0Wql9aKMOFQlFODG1w= X-Google-Smtp-Source: APXvYqzzEgDfDThZlgrBSHnE6dlyA27yZPDdjMp+dpA4B1+CbNfEsBCId02HF5iR2VeYOGkCbK28Ag== X-Received: by 2002:ae9:eb53:: with SMTP id b80mr68407120qkg.172.1560900541965; Tue, 18 Jun 2019 16:29:01 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.28.58 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:01 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Daniel Ferreira , Junio C Hamano Subject: [GSoC][PATCH v7 03/10] dir-iterator: add tests for dir-iterator API Date: Tue, 18 Jun 2019 20:27:40 -0300 Message-Id: <60c5fc6ad28a01c767befeb06601eaf6db4ca42a.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Daniel Ferreira Create t/helper/test-dir-iterator.c, which prints relevant information about a directory tree iterated over with dir-iterator. Create t/t0066-dir-iterator.sh, which tests that dir-iterator does iterate through a whole directory tree as expected. Signed-off-by: Daniel Ferreira [matheus.bernardino: update to use test-tool and some minor aesthetics] Helped-by: Matheus Tavares Signed-off-by: Matheus Tavares --- Makefile | 1 + t/helper/test-dir-iterator.c | 33 ++++++++++++++++++++++ t/helper/test-tool.c | 1 + t/helper/test-tool.h | 1 + t/t0066-dir-iterator.sh | 55 ++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 t/helper/test-dir-iterator.c create mode 100755 t/t0066-dir-iterator.sh diff --git a/Makefile b/Makefile index f58bf14c7b..7e2a44cccc 100644 --- a/Makefile +++ b/Makefile @@ -704,6 +704,7 @@ TEST_BUILTINS_OBJS += test-config.o TEST_BUILTINS_OBJS += test-ctype.o TEST_BUILTINS_OBJS += test-date.o TEST_BUILTINS_OBJS += test-delta.o +TEST_BUILTINS_OBJS += test-dir-iterator.o TEST_BUILTINS_OBJS += test-drop-caches.o TEST_BUILTINS_OBJS += test-dump-cache-tree.o TEST_BUILTINS_OBJS += test-dump-fsmonitor.o diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c new file mode 100644 index 0000000000..84f50bed8c --- /dev/null +++ b/t/helper/test-dir-iterator.c @@ -0,0 +1,33 @@ +#include "test-tool.h" +#include "git-compat-util.h" +#include "strbuf.h" +#include "iterator.h" +#include "dir-iterator.h" + +/* Argument is a directory path to iterate over */ +int cmd__dir_iterator(int argc, const char **argv) +{ + struct strbuf path = STRBUF_INIT; + struct dir_iterator *diter; + + if (argc < 2) + die("BUG: test-dir-iterator needs one argument"); + + strbuf_add(&path, argv[1], strlen(argv[1])); + + diter = dir_iterator_begin(path.buf); + + while (dir_iterator_advance(diter) == ITER_OK) { + if (S_ISDIR(diter->st.st_mode)) + printf("[d] "); + else if (S_ISREG(diter->st.st_mode)) + printf("[f] "); + else + printf("[?] "); + + printf("(%s) [%s] %s\n", diter->relative_path, diter->basename, + diter->path.buf); + } + + return 0; +} diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 087a8c0cc9..7bc9bb231e 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -19,6 +19,7 @@ static struct test_cmd cmds[] = { { "ctype", cmd__ctype }, { "date", cmd__date }, { "delta", cmd__delta }, + { "dir-iterator", cmd__dir_iterator }, { "drop-caches", cmd__drop_caches }, { "dump-cache-tree", cmd__dump_cache_tree }, { "dump-fsmonitor", cmd__dump_fsmonitor }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 7e703f3038..ec0ffbd0cb 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -9,6 +9,7 @@ int cmd__config(int argc, const char **argv); int cmd__ctype(int argc, const char **argv); int cmd__date(int argc, const char **argv); int cmd__delta(int argc, const char **argv); +int cmd__dir_iterator(int argc, const char **argv); int cmd__drop_caches(int argc, const char **argv); int cmd__dump_cache_tree(int argc, const char **argv); int cmd__dump_fsmonitor(int argc, const char **argv); diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh new file mode 100755 index 0000000000..6e06dc038d --- /dev/null +++ b/t/t0066-dir-iterator.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='Test the dir-iterator functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir -p dir && + mkdir -p dir/a/b/c/ && + >dir/b && + >dir/c && + mkdir -p dir/d/e/d/ && + >dir/a/b/c/d && + >dir/a/e && + >dir/d/e/d/a && + + mkdir -p dir2/a/b/c/ && + >dir2/a/b/c/d +' + +test_expect_success 'dir-iterator should iterate through all files' ' + cat >expected-iteration-sorted-output <<-EOF && + [d] (a) [a] ./dir/a + [d] (a/b) [b] ./dir/a/b + [d] (a/b/c) [c] ./dir/a/b/c + [d] (d) [d] ./dir/d + [d] (d/e) [e] ./dir/d/e + [d] (d/e/d) [d] ./dir/d/e/d + [f] (a/b/c/d) [d] ./dir/a/b/c/d + [f] (a/e) [e] ./dir/a/e + [f] (b) [b] ./dir/b + [f] (c) [c] ./dir/c + [f] (d/e/d/a) [a] ./dir/d/e/d/a + EOF + + test-tool dir-iterator ./dir >out && + sort ./actual-iteration-sorted-output && + + test_cmp expected-iteration-sorted-output actual-iteration-sorted-output +' + +test_expect_success 'dir-iterator should list files in the correct order' ' + cat >expected-pre-order-output <<-EOF && + [d] (a) [a] ./dir2/a + [d] (a/b) [b] ./dir2/a/b + [d] (a/b/c) [c] ./dir2/a/b/c + [f] (a/b/c/d) [d] ./dir2/a/b/c/d + EOF + + test-tool dir-iterator ./dir2 >actual-pre-order-output && + + test_cmp expected-pre-order-output actual-pre-order-output +' + +test_done From patchwork Tue Jun 18 23:27:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003113 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0097E1395 for ; Tue, 18 Jun 2019 23:29:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3D3228901 for ; Tue, 18 Jun 2019 23:29:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D81B828ACA; Tue, 18 Jun 2019 23:29:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7BC9B28901 for ; Tue, 18 Jun 2019 23:29:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729098AbfFRX3J (ORCPT ); Tue, 18 Jun 2019 19:29:09 -0400 Received: from mail-qt1-f193.google.com ([209.85.160.193]:33133 "EHLO mail-qt1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3J (ORCPT ); Tue, 18 Jun 2019 19:29:09 -0400 Received: by mail-qt1-f193.google.com with SMTP id x2so17711051qtr.0 for ; Tue, 18 Jun 2019 16:29:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CqQHOlwlfENkwc05/cG9Y2S77go+PAKki+Y1xBT2URM=; b=DIsFbjIxO1FXBBNKP8jjjxHOPgqiC0qnzqcLbOaD70idRR2Oe7Qytem49li77aAIbq 7YWNl6b02hTGiNyvHYQQZTGHjlfEqoyNnT7XsAFTJ8PvAcZ9Al44H2z7HVgY5LF1Qx6u 2QtoQ5CpSnamqCOcEBQPK/lrtCcNzUrN8ptih19H77ODqJYVFw/4stjVuMZ0Jasb6+gV CeQUCP9A2vIJlGYJDxphcnbx8hKDeFQ2Nv1LEFo39UZ84jlGNL3UEW5DUb6CwVCgG1us GXv3q1rjonPozp7FNePDg2ZgcUzvxcNJhAwnmmA7iqCdAXvvgoL0Osk5isXilcKz05O1 7+fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CqQHOlwlfENkwc05/cG9Y2S77go+PAKki+Y1xBT2URM=; b=nPI5BV8FoMsdPpRM6OUf43fwUAEXIc21PtcCDo1bOJ4pbomZ7gNyF36axtJqyndAtc 0kpA7VOJBNL40UhpHFAe/aVPVSjqsd5d32u5/BF2Kxnr/H7V1gVvdsimFWr3ntHaYIUs KrrVy/vViK7jSPoS6fLfyzrAbtZm6vHv0uVYS0QGbOnoRLzVy32j9atqTFCXJVNe3+iO huaj/FH0UDUlQSV432Z9lKgHp3PLwKLFwVxaPhlAsMK3d3Mm5K7uZSalgDXX23veyH+s zGIPJyrBu/lu86bqfy3IdI6+wXOocPbAkQWg9nret/z5720xpYr3kstfVLFpeOAS0jhH Agkw== X-Gm-Message-State: APjAAAXR7DxkTpRe15hM/SICGCf2k7mHgGKo1NWs3NhP6CnFC/2NwHeM Q/++n3kgQpT24sb3xHcx3kDYEJMDbWs= X-Google-Smtp-Source: APXvYqx+YgaIql4y1H152zHK7kdl73puLl/tY1ESYGMHvbwTFu+Atij/fsCPHhuJQuaVvbLaQOt2Wg== X-Received: by 2002:a05:6214:248:: with SMTP id k8mr30270010qvt.200.1560900548393; Tue, 18 Jun 2019 16:29:08 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.05 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:07 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Junio C Hamano , Michael Haggerty Subject: [GSoC][PATCH v7 04/10] dir-iterator: use warning_errno when possible Date: Tue, 18 Jun 2019 20:27:41 -0300 Message-Id: <8b060b3bf4389d337d84d53cebcc8b02aa1a7a74.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Change warning(..., strerror(errno)) by warning_errno(...). This helps to unify warning display besides simplifying a bit the code. Also, improve warning messages by surrounding paths with quotation marks and using more meaningful statements. Signed-off-by: Matheus Tavares --- dir-iterator.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/dir-iterator.c b/dir-iterator.c index f2dcd82fde..0c8880868a 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -71,8 +71,8 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) level->dir = opendir(iter->base.path.buf); if (!level->dir && errno != ENOENT) { - warning("error opening directory %s: %s", - iter->base.path.buf, strerror(errno)); + warning_errno("error opening directory '%s'", + iter->base.path.buf); /* Popping the level is handled below */ } @@ -122,11 +122,11 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) if (!de) { /* This level is exhausted; pop up a level. */ if (errno) { - warning("error reading directory %s: %s", - iter->base.path.buf, strerror(errno)); + warning_errno("error reading directory '%s'", + iter->base.path.buf); } else if (closedir(level->dir)) - warning("error closing directory %s: %s", - iter->base.path.buf, strerror(errno)); + warning_errno("error closing directory '%s'", + iter->base.path.buf); level->dir = NULL; if (--iter->levels_nr == 0) @@ -140,9 +140,8 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) strbuf_addstr(&iter->base.path, de->d_name); if (lstat(iter->base.path.buf, &iter->base.st) < 0) { if (errno != ENOENT) - warning("error reading path '%s': %s", - iter->base.path.buf, - strerror(errno)); + warning_errno("failed to stat '%s'", + iter->base.path.buf); continue; } @@ -170,9 +169,11 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator) &iter->levels[iter->levels_nr - 1]; if (level->dir && closedir(level->dir)) { + int saved_errno = errno; strbuf_setlen(&iter->base.path, level->prefix_len); - warning("error closing directory %s: %s", - iter->base.path.buf, strerror(errno)); + errno = saved_errno; + warning_errno("error closing directory '%s'", + iter->base.path.buf); } } From patchwork Tue Jun 18 23:27:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3E7961395 for ; Tue, 18 Jun 2019 23:29:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C38D28901 for ; Tue, 18 Jun 2019 23:29:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1E8EF28ACA; Tue, 18 Jun 2019 23:29:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D4C928901 for ; Tue, 18 Jun 2019 23:29:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729201AbfFRX3T (ORCPT ); Tue, 18 Jun 2019 19:29:19 -0400 Received: from mail-qk1-f196.google.com ([209.85.222.196]:39814 "EHLO mail-qk1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3T (ORCPT ); Tue, 18 Jun 2019 19:29:19 -0400 Received: by mail-qk1-f196.google.com with SMTP id i125so9748536qkd.6 for ; Tue, 18 Jun 2019 16:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n/fVbtc+e4k81hyyN9o4Pt+aT8gInbHXcWDi8q9Ax64=; b=uDNxdAFabGUimKE8QMrZmBCvXXxmXbvL4uZ9W6LK+OWg+eLVFj56PtqJwbVluDhllP X9Q5FcLMH8y896q5IeXAcgQ+bSLstDHC9DQOeHpcNo6gLPE2kbQXUaENXwrydO2rFBEm OlhOWjH6wO7w0oF+f6FV9Cy1C2kj2gL7c6cP4Mgd2P/PlXpZeeJvyW7YSDBv0+JezcYm jR3/r51Gug7tFDxzRIq8hN4AL4BVoN1vt0znbHW1DAgZMjE89Kcl8NfhzAKKyNeTHvp1 KB+Sf8MB2M2Vf3wRQvy3wj9pkozAD9mIMZ+QhZ9bzHJq7siyhI/54okXX/wk5dhsW67A sm7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=n/fVbtc+e4k81hyyN9o4Pt+aT8gInbHXcWDi8q9Ax64=; b=TDW8Ygfob1T33glmsG4tD4qfpmMAfMOYMeuasrtovKdCi2x6EI+bTwqHN1eGfim0XX uLOqIu85v0b56wB4f7hIcTeJVXGdpu1doyPgE93ciPLeQzR7PiWRhD/ZCQwwga2TSIFR f8f2H1xiNkYfX1BkQgn/mHKqFkTDCYg6VKAdWcVR4EEMZjsmtzQCjoADHwGEzBCB6olj v3CQWkdj27IXUDazJhOZuDHR9X2YZyHDZsChEEYt2n2T9lYR/o7Bc9VR90o9w2O09XLF 0MSSbRZK8l3a9pflnha+7ArSI19Cb6eN2CNi/52l/T66jMHah/xoq/lMaqAKxWIQfvcu jZSw== X-Gm-Message-State: APjAAAWooXL7ffnVsWrXXgCLTx+I9QKz0K0KAAzua/4YBlYNFESg0O6c xh9gGQqShFejJRh1lYS3iOkoSKWvnik= X-Google-Smtp-Source: APXvYqyVzMB8kD+I0VfoAhOviDlgYFjmbkd7f1WDCHKS4uyFrf5DTFBPCgMToju5m2KXJ7p6C+FREg== X-Received: by 2002:ae9:e20c:: with SMTP id c12mr96335250qkc.210.1560900557590; Tue, 18 Jun 2019 16:29:17 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.13 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:17 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Daniel Ferreira , Jeff King , Johannes Schindelin , Michael Haggerty , Junio C Hamano , Ramsay Jones Subject: [GSoC][PATCH v7 05/10] dir-iterator: refactor state machine model Date: Tue, 18 Jun 2019 20:27:42 -0300 Message-Id: X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP dir_iterator_advance() is a large function with two nested loops. Let's improve its readability factoring out three functions and simplifying its mechanics. The refactored model will no longer depend on level.initialized and level.dir_state to keep track of the iteration state and will perform on a single loop. Also, dir_iterator_begin() currently does not check if the given string represents a valid directory path. Since the refactored model will have to stat() the given path at initialization, let's also check for this kind of error and make dir_iterator_begin() return NULL, on failures, with errno appropriately set. And add tests for this new behavior. Improve documentation at dir-iteration.h and code comments at dir-iterator.c to reflect the changes and eliminate possible ambiguities. Finally, adjust refs/files-backend.c to check for now possible dir_iterator_begin() failures. Original-patch-by: Daniel Ferreira Signed-off-by: Matheus Tavares --- dir-iterator.c | 234 ++++++++++++++++++----------------- dir-iterator.h | 15 ++- refs/files-backend.c | 17 ++- t/helper/test-dir-iterator.c | 5 + t/t0066-dir-iterator.sh | 13 ++ 5 files changed, 163 insertions(+), 121 deletions(-) diff --git a/dir-iterator.c b/dir-iterator.c index 0c8880868a..594fe4d67b 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -4,8 +4,6 @@ #include "dir-iterator.h" struct dir_iterator_level { - int initialized; - DIR *dir; /* @@ -13,16 +11,6 @@ struct dir_iterator_level { * (including a trailing '/'): */ size_t prefix_len; - - /* - * The last action that has been taken with the current entry - * (needed for directories, which have to be included in the - * iteration and also iterated into): - */ - enum { - DIR_STATE_ITER, - DIR_STATE_RECURSE - } dir_state; }; /* @@ -34,9 +22,11 @@ struct dir_iterator_int { struct dir_iterator base; /* - * The number of levels currently on the stack. This is always - * at least 1, because when it becomes zero the iteration is - * ended and this struct is freed. + * The number of levels currently on the stack. After the first + * call to dir_iterator_begin(), if it succeeds to open the + * first level's dir, this will always be at least 1. Then, + * when it comes to zero the iteration is ended and this + * struct is freed. */ size_t levels_nr; @@ -50,113 +40,118 @@ struct dir_iterator_int { struct dir_iterator_level *levels; }; +/* + * Push a level in the iter stack and initialize it with information from + * the directory pointed by iter->base->path. It is assumed that this + * strbuf points to a valid directory path. Return 0 on success and -1 + * otherwise, leaving the stack unchanged. + */ +static int push_level(struct dir_iterator_int *iter) +{ + struct dir_iterator_level *level; + + ALLOC_GROW(iter->levels, iter->levels_nr + 1, iter->levels_alloc); + level = &iter->levels[iter->levels_nr++]; + + if (!is_dir_sep(iter->base.path.buf[iter->base.path.len - 1])) + strbuf_addch(&iter->base.path, '/'); + level->prefix_len = iter->base.path.len; + + level->dir = opendir(iter->base.path.buf); + if (!level->dir) { + if (errno != ENOENT) { + warning_errno("error opening directory '%s'", + iter->base.path.buf); + } + iter->levels_nr--; + return -1; + } + + return 0; +} + +/* + * Pop the top level on the iter stack, releasing any resources associated + * with it. Return the new value of iter->levels_nr. + */ +static int pop_level(struct dir_iterator_int *iter) +{ + struct dir_iterator_level *level = + &iter->levels[iter->levels_nr - 1]; + + if (level->dir && closedir(level->dir)) + warning_errno("error closing directory '%s'", + iter->base.path.buf); + level->dir = NULL; + + return --iter->levels_nr; +} + +/* + * Populate iter->base with the necessary information on the next iteration + * entry, represented by the given dirent de. Return 0 on success and -1 + * otherwise. + */ +static int prepare_next_entry_data(struct dir_iterator_int *iter, + struct dirent *de) +{ + strbuf_addstr(&iter->base.path, de->d_name); + /* + * We have to reset these because the path strbuf might have + * been realloc()ed at the previous strbuf_addstr(). + */ + iter->base.relative_path = iter->base.path.buf + + iter->levels[0].prefix_len; + iter->base.basename = iter->base.path.buf + + iter->levels[iter->levels_nr - 1].prefix_len; + + if (lstat(iter->base.path.buf, &iter->base.st)) { + if (errno != ENOENT) + warning_errno("failed to stat '%s'", iter->base.path.buf); + return -1; + } + + return 0; +} + int dir_iterator_advance(struct dir_iterator *dir_iterator) { struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator; + if (S_ISDIR(iter->base.st.st_mode)) { + if (push_level(iter) && iter->levels_nr == 0) { + /* Pushing the first level failed */ + return dir_iterator_abort(dir_iterator); + } + } + + /* Loop until we find an entry that we can give back to the caller. */ while (1) { + struct dirent *de; struct dir_iterator_level *level = &iter->levels[iter->levels_nr - 1]; - struct dirent *de; - if (!level->initialized) { - /* - * Note: dir_iterator_begin() ensures that - * path is not the empty string. - */ - if (!is_dir_sep(iter->base.path.buf[iter->base.path.len - 1])) - strbuf_addch(&iter->base.path, '/'); - level->prefix_len = iter->base.path.len; - - level->dir = opendir(iter->base.path.buf); - if (!level->dir && errno != ENOENT) { - warning_errno("error opening directory '%s'", + strbuf_setlen(&iter->base.path, level->prefix_len); + errno = 0; + de = readdir(level->dir); + + if (!de) { + if (errno) + warning_errno("error reading directory '%s'", iter->base.path.buf); - /* Popping the level is handled below */ - } - - level->initialized = 1; - } else if (S_ISDIR(iter->base.st.st_mode)) { - if (level->dir_state == DIR_STATE_ITER) { - /* - * The directory was just iterated - * over; now prepare to iterate into - * it. - */ - level->dir_state = DIR_STATE_RECURSE; - ALLOC_GROW(iter->levels, iter->levels_nr + 1, - iter->levels_alloc); - level = &iter->levels[iter->levels_nr++]; - level->initialized = 0; - continue; - } else { - /* - * The directory has already been - * iterated over and iterated into; - * we're done with it. - */ - } + else if (pop_level(iter) == 0) + return dir_iterator_abort(dir_iterator); + continue; } - if (!level->dir) { - /* - * This level is exhausted (or wasn't opened - * successfully); pop up a level. - */ - if (--iter->levels_nr == 0) - return dir_iterator_abort(dir_iterator); + if (is_dot_or_dotdot(de->d_name)) + continue; + if (prepare_next_entry_data(iter, de)) continue; - } - /* - * Loop until we find an entry that we can give back - * to the caller: - */ - while (1) { - strbuf_setlen(&iter->base.path, level->prefix_len); - errno = 0; - de = readdir(level->dir); - - if (!de) { - /* This level is exhausted; pop up a level. */ - if (errno) { - warning_errno("error reading directory '%s'", - iter->base.path.buf); - } else if (closedir(level->dir)) - warning_errno("error closing directory '%s'", - iter->base.path.buf); - - level->dir = NULL; - if (--iter->levels_nr == 0) - return dir_iterator_abort(dir_iterator); - break; - } - - if (is_dot_or_dotdot(de->d_name)) - continue; - - strbuf_addstr(&iter->base.path, de->d_name); - if (lstat(iter->base.path.buf, &iter->base.st) < 0) { - if (errno != ENOENT) - warning_errno("failed to stat '%s'", - iter->base.path.buf); - continue; - } - - /* - * We have to set these each time because - * the path strbuf might have been realloc()ed. - */ - iter->base.relative_path = - iter->base.path.buf + iter->levels[0].prefix_len; - iter->base.basename = - iter->base.path.buf + level->prefix_len; - level->dir_state = DIR_STATE_ITER; - - return ITER_OK; - } + return ITER_OK; } } @@ -187,17 +182,32 @@ struct dir_iterator *dir_iterator_begin(const char *path) { struct dir_iterator_int *iter = xcalloc(1, sizeof(*iter)); struct dir_iterator *dir_iterator = &iter->base; - - if (!path || !*path) - BUG("empty path passed to dir_iterator_begin()"); + int saved_errno; strbuf_init(&iter->base.path, PATH_MAX); strbuf_addstr(&iter->base.path, path); ALLOC_GROW(iter->levels, 10, iter->levels_alloc); + iter->levels_nr = 0; - iter->levels_nr = 1; - iter->levels[0].initialized = 0; + /* + * Note: stat already checks for NULL or empty strings and + * inexistent paths. + */ + if (stat(iter->base.path.buf, &iter->base.st) < 0) { + saved_errno = errno; + goto error_out; + } + + if (!S_ISDIR(iter->base.st.st_mode)) { + saved_errno = ENOTDIR; + goto error_out; + } return dir_iterator; + +error_out: + dir_iterator_abort(dir_iterator); + errno = saved_errno; + return NULL; } diff --git a/dir-iterator.h b/dir-iterator.h index 970793d07a..0822821e56 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -8,19 +8,23 @@ * * Iterate over a directory tree, recursively, including paths of all * types and hidden paths. Skip "." and ".." entries and don't follow - * symlinks except for the original path. + * symlinks except for the original path. Note that the original path + * is not included in the iteration. * * Every time dir_iterator_advance() is called, update the members of * the dir_iterator structure to reflect the next path in the * iteration. The order that paths are iterated over within a - * directory is undefined, but directory paths are always iterated - * over before the subdirectory contents. + * directory is undefined, directory paths are always given before + * their contents. * * A typical iteration looks like this: * * int ok; * struct iterator *iter = dir_iterator_begin(path); * + * if (!iter) + * goto error_handler; + * * while ((ok = dir_iterator_advance(iter)) == ITER_OK) { * if (want_to_stop_iteration()) { * ok = dir_iterator_abort(iter); @@ -59,8 +63,9 @@ struct dir_iterator { }; /* - * Start a directory iteration over path. Return a dir_iterator that - * holds the internal state of the iteration. + * Start a directory iteration over path. On success, return a + * dir_iterator that holds the internal state of the iteration. + * In case of failure, return NULL and set errno accordingly. * * The iteration includes all paths under path, not including path * itself and not including "." or ".." entries. diff --git a/refs/files-backend.c b/refs/files-backend.c index 63e55e6773..7ed81046d4 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -2143,13 +2143,22 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = { static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, const char *gitdir) { - struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter)); - struct ref_iterator *ref_iterator = &iter->base; + struct dir_iterator *diter; + struct files_reflog_iterator *iter; + struct ref_iterator *ref_iterator; struct strbuf sb = STRBUF_INIT; - base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0); strbuf_addf(&sb, "%s/logs", gitdir); - iter->dir_iterator = dir_iterator_begin(sb.buf); + + diter = dir_iterator_begin(sb.buf); + if(!diter) + return empty_ref_iterator_begin(); + + iter = xcalloc(1, sizeof(*iter)); + ref_iterator = &iter->base; + + base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0); + iter->dir_iterator = diter; iter->ref_store = ref_store; strbuf_release(&sb); diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c index 84f50bed8c..fab1ff6237 100644 --- a/t/helper/test-dir-iterator.c +++ b/t/helper/test-dir-iterator.c @@ -17,6 +17,11 @@ int cmd__dir_iterator(int argc, const char **argv) diter = dir_iterator_begin(path.buf); + if (!diter) { + printf("dir_iterator_begin failure: %d\n", errno); + exit(EXIT_FAILURE); + } + while (dir_iterator_advance(diter) == ITER_OK) { if (S_ISDIR(diter->st.st_mode)) printf("[d] "); diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh index 6e06dc038d..c739ed7911 100755 --- a/t/t0066-dir-iterator.sh +++ b/t/t0066-dir-iterator.sh @@ -52,4 +52,17 @@ test_expect_success 'dir-iterator should list files in the correct order' ' test_cmp expected-pre-order-output actual-pre-order-output ' +test_expect_success 'begin should fail upon inexistent paths' ' + test_must_fail test-tool dir-iterator ./inexistent-path \ + >actual-inexistent-path-output && + echo "dir_iterator_begin failure: 2" >expected-inexistent-path-output && + test_cmp expected-inexistent-path-output actual-inexistent-path-output +' + +test_expect_success 'begin should fail upon non directory paths' ' + test_must_fail test-tool dir-iterator ./dir/b >actual-non-dir-output && + echo "dir_iterator_begin failure: 20" >expected-non-dir-output && + test_cmp expected-non-dir-output actual-non-dir-output +' + test_done From patchwork Tue Jun 18 23:27:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003117 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0FB5A14B6 for ; Tue, 18 Jun 2019 23:29:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F1FA028901 for ; Tue, 18 Jun 2019 23:29:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E5EE128ACA; Tue, 18 Jun 2019 23:29:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CFE6A28901 for ; Tue, 18 Jun 2019 23:29:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729264AbfFRX30 (ORCPT ); Tue, 18 Jun 2019 19:29:26 -0400 Received: from mail-qk1-f195.google.com ([209.85.222.195]:41790 "EHLO mail-qk1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX30 (ORCPT ); Tue, 18 Jun 2019 19:29:26 -0400 Received: by mail-qk1-f195.google.com with SMTP id c11so9751981qkk.8 for ; Tue, 18 Jun 2019 16:29:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g6NMU4HTDCdyZ6Xsudagjf+yIm1J5rWUUK3tcAigeCE=; b=bXtsO8NZB1M38A1+OeWEulv2vIqCL8ygRzvliAAq0iHsGPLFEcjexCkFEH6520ucC3 mn37hWf2rCV//JkxDdw0dHSES+YwCXsvEgcZbY8f4ASjyIOtvthTXv4KANxM1T+XmAot XWioDKol43uMzKw2AJoXXGTcHZdBDu6QTTr1aSb7hQpvmoYtWzkD/t4y2Vxh6achJaLd sRmEDmdX2HMPyCejedDx9Qi5PfCT2WSLRrukowGANExjKtEeLE4DiYXWPfXt0R/8PDem XBkWUoOVS8BFHOxSRcxsTENvuKzmIvHudS3vT2aSJVrPQ5kLh8WrbS+TNhptS3BXkynp ewEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g6NMU4HTDCdyZ6Xsudagjf+yIm1J5rWUUK3tcAigeCE=; b=aXzL68eH5dI3DZDtycRp48BqGrIV35FUYqqXm2VXbuOughgADraTLQ4Tkcjbj4110o 05urOVO6MYt3URy+S+ywqEO6N3hd55XYzwkd0Ynz8Zp6iSSXLzWrzLUMqNRdW/zhHS5d YY2/UT8bewuXiyjn5mCqZk8gq/wyGts/JA6a9PaZliWjtjjv96p7v6h9ZP+oaY4/rOeH XVT/Tj2odlK07g2DWZVvYouNeJ2CSZ91Rsrd0HnVnRDDlMcIKk77Dn9UZQftrYISFLwU mAEmwmDXe5nU0/zy29rUnDajLMAL6sIKCsXlxC6SUhaLr9WBF3jkiB+8S3Is/+6O3pP0 mWTg== X-Gm-Message-State: APjAAAX3prRqXo1ZkV0U2bWfiD0wBatKx/HcZtcGQ9nmxarWIm3NhTxo mOXreJouHIyNg9/ZRi09ozA9cJVpJzg= X-Google-Smtp-Source: APXvYqwuUBvzVJARZwu9V+aJrwBP3nnQlEGXYJYO6MUPgrR+rOf9CzVLS3BplUlZCC+Zymk3TRzHQA== X-Received: by 2002:a05:620a:44:: with SMTP id t4mr7690713qkt.189.1560900565074; Tue, 18 Jun 2019 16:29:25 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.21 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:24 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Michael Haggerty , Daniel Ferreira , Ramsay Jones , Junio C Hamano Subject: [GSoC][PATCH v7 06/10] dir-iterator: add flags parameter to dir_iterator_begin Date: Tue, 18 Jun 2019 20:27:43 -0300 Message-Id: <5a678ee74de42f1373deeed718fa24d368347d13.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add the possibility of giving flags to dir_iterator_begin to initialize a dir-iterator with special options. Currently possible flags are: - DIR_ITERATOR_PEDANTIC, which makes dir_iterator_advance abort immediately in the case of an error, instead of keep looking for the next valid entry; - DIR_ITERATOR_FOLLOW_SYMLINKS, which makes the iterator follow symlinks and include linked directories' contents in the iteration. These new flags will be used in a subsequent patch. Also add tests for the flags' usage and adjust refs/files-backend.c to the new dir_iterator_begin signature. Signed-off-by: Matheus Tavares --- dir-iterator.c | 82 +++++++++++++++++++++++++------ dir-iterator.h | 51 ++++++++++++++----- refs/files-backend.c | 2 +- t/helper/test-dir-iterator.c | 34 ++++++++++--- t/t0066-dir-iterator.sh | 95 ++++++++++++++++++++++++++++++++++++ 5 files changed, 229 insertions(+), 35 deletions(-) diff --git a/dir-iterator.c b/dir-iterator.c index 594fe4d67b..52db87bdc9 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -6,6 +6,9 @@ struct dir_iterator_level { DIR *dir; + /* The inode number of this level's directory. */ + ino_t ino; + /* * The length of the directory part of path at this level * (including a trailing '/'): @@ -38,13 +41,16 @@ struct dir_iterator_int { * that will be included in this iteration. */ struct dir_iterator_level *levels; + + /* Combination of flags for this dir-iterator */ + unsigned int flags; }; /* * Push a level in the iter stack and initialize it with information from * the directory pointed by iter->base->path. It is assumed that this * strbuf points to a valid directory path. Return 0 on success and -1 - * otherwise, leaving the stack unchanged. + * otherwise, setting errno accordingly and leaving the stack unchanged. */ static int push_level(struct dir_iterator_int *iter) { @@ -56,14 +62,17 @@ static int push_level(struct dir_iterator_int *iter) if (!is_dir_sep(iter->base.path.buf[iter->base.path.len - 1])) strbuf_addch(&iter->base.path, '/'); level->prefix_len = iter->base.path.len; + level->ino = iter->base.st.st_ino; level->dir = opendir(iter->base.path.buf); if (!level->dir) { + int saved_errno = errno; if (errno != ENOENT) { warning_errno("error opening directory '%s'", iter->base.path.buf); } iter->levels_nr--; + errno = saved_errno; return -1; } @@ -90,11 +99,13 @@ static int pop_level(struct dir_iterator_int *iter) /* * Populate iter->base with the necessary information on the next iteration * entry, represented by the given dirent de. Return 0 on success and -1 - * otherwise. + * otherwise, setting errno accordingly. */ static int prepare_next_entry_data(struct dir_iterator_int *iter, struct dirent *de) { + int err, saved_errno; + strbuf_addstr(&iter->base.path, de->d_name); /* * We have to reset these because the path strbuf might have @@ -105,12 +116,34 @@ static int prepare_next_entry_data(struct dir_iterator_int *iter, iter->base.basename = iter->base.path.buf + iter->levels[iter->levels_nr - 1].prefix_len; - if (lstat(iter->base.path.buf, &iter->base.st)) { - if (errno != ENOENT) - warning_errno("failed to stat '%s'", iter->base.path.buf); - return -1; - } + if (iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS) + err = stat(iter->base.path.buf, &iter->base.st); + else + err = lstat(iter->base.path.buf, &iter->base.st); + + saved_errno = errno; + if (err && errno != ENOENT) + warning_errno("failed to stat '%s'", iter->base.path.buf); + + errno = saved_errno; + return err; +} + +/* + * Look for a recursive symlink at iter->base.path pointing to any directory on + * the previous stack levels. If it is found, return 1. If not, return 0. + */ +static int find_recursive_symlinks(struct dir_iterator_int *iter) +{ + int i; + + if (!(iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS) || + !S_ISDIR(iter->base.st.st_mode)) + return 0; + for (i = 0; i < iter->levels_nr; ++i) + if (iter->base.st.st_ino == iter->levels[i].ino) + return 1; return 0; } @@ -119,11 +152,11 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator; - if (S_ISDIR(iter->base.st.st_mode)) { - if (push_level(iter) && iter->levels_nr == 0) { - /* Pushing the first level failed */ - return dir_iterator_abort(dir_iterator); - } + if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) { + if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) + goto error_out; + if (iter->levels_nr == 0) + goto error_out; } /* Loop until we find an entry that we can give back to the caller. */ @@ -137,22 +170,38 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) de = readdir(level->dir); if (!de) { - if (errno) + if (errno) { warning_errno("error reading directory '%s'", iter->base.path.buf); - else if (pop_level(iter) == 0) + if (iter->flags & DIR_ITERATOR_PEDANTIC) + goto error_out; + } else if (pop_level(iter) == 0) { return dir_iterator_abort(dir_iterator); + } continue; } if (is_dot_or_dotdot(de->d_name)) continue; - if (prepare_next_entry_data(iter, de)) + if (prepare_next_entry_data(iter, de)) { + if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) + goto error_out; continue; + } + + if (find_recursive_symlinks(iter)) { + warning("ignoring recursive symlink at '%s'", + iter->base.path.buf); + continue; + } return ITER_OK; } + +error_out: + dir_iterator_abort(dir_iterator); + return ITER_ERROR; } int dir_iterator_abort(struct dir_iterator *dir_iterator) @@ -178,7 +227,7 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator) return ITER_DONE; } -struct dir_iterator *dir_iterator_begin(const char *path) +struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) { struct dir_iterator_int *iter = xcalloc(1, sizeof(*iter)); struct dir_iterator *dir_iterator = &iter->base; @@ -189,6 +238,7 @@ struct dir_iterator *dir_iterator_begin(const char *path) ALLOC_GROW(iter->levels, 10, iter->levels_alloc); iter->levels_nr = 0; + iter->flags = flags; /* * Note: stat already checks for NULL or empty strings and diff --git a/dir-iterator.h b/dir-iterator.h index 0822821e56..42751091a5 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -20,7 +20,8 @@ * A typical iteration looks like this: * * int ok; - * struct iterator *iter = dir_iterator_begin(path); + * unsigned int flags = DIR_ITERATOR_PEDANTIC; + * struct dir_iterator *iter = dir_iterator_begin(path, flags); * * if (!iter) * goto error_handler; @@ -44,6 +45,25 @@ * dir_iterator_advance() again. */ +/* + * Flags for dir_iterator_begin: + * + * - DIR_ITERATOR_PEDANTIC: override dir-iterator's default behavior + * in case of an error at dir_iterator_advance(), which is to keep + * looking for a next valid entry. With this flag, resources are freed + * and ITER_ERROR is returned immediately. In both cases, a meaningful + * warning is emitted. Note: ENOENT errors are always ignored so that + * the API users may remove files during iteration. + * + * - DIR_ITERATOR_FOLLOW_SYMLINKS: make dir-iterator follow symlinks. + * i.e., linked directories' contents will be iterated over and + * iter->base.st will contain information on the referred files, + * not the symlinks themselves, which is the default behavior. + * Recursive symlinks are skipped with a warning and broken symlinks + * are ignored. + */ +#define DIR_ITERATOR_PEDANTIC (1 << 0) +#define DIR_ITERATOR_FOLLOW_SYMLINKS (1 << 1) + struct dir_iterator { /* The current path: */ struct strbuf path; @@ -58,29 +78,38 @@ struct dir_iterator { /* The current basename: */ const char *basename; - /* The result of calling lstat() on path: */ + /* + * The result of calling lstat() on path; or stat(), if the + * DIR_ITERATOR_FOLLOW_SYMLINKS flag was set at + * dir_iterator's initialization. + */ struct stat st; }; /* - * Start a directory iteration over path. On success, return a - * dir_iterator that holds the internal state of the iteration. - * In case of failure, return NULL and set errno accordingly. + * Start a directory iteration over path with the combination of + * options specified by flags. On success, return a dir_iterator + * that holds the internal state of the iteration. In case of + * failure, return NULL and set errno accordingly. * * The iteration includes all paths under path, not including path * itself and not including "." or ".." entries. * - * path is the starting directory. An internal copy will be made. + * Parameters are: + * - path is the starting directory. An internal copy will be made. + * - flags is a combination of the possible flags to initialize a + * dir-iterator or 0 for default behavior. */ -struct dir_iterator *dir_iterator_begin(const char *path); +struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags); /* * Advance the iterator to the first or next item and return ITER_OK. * If the iteration is exhausted, free the dir_iterator and any - * resources associated with it and return ITER_DONE. On error, free - * dir_iterator and associated resources and return ITER_ERROR. It is - * a bug to use iterator or call this function again after it has - * returned ITER_DONE or ITER_ERROR. + * resources associated with it and return ITER_DONE. + * + * It is a bug to use iterator or call this function again after it + * has returned ITER_DONE or ITER_ERROR (which may be returned iff + * the DIR_ITERATOR_PEDANTIC flag was set). */ int dir_iterator_advance(struct dir_iterator *iterator); diff --git a/refs/files-backend.c b/refs/files-backend.c index 7ed81046d4..b1f8f53a09 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -2150,7 +2150,7 @@ static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, strbuf_addf(&sb, "%s/logs", gitdir); - diter = dir_iterator_begin(sb.buf); + diter = dir_iterator_begin(sb.buf, 0); if(!diter) return empty_ref_iterator_begin(); diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c index fab1ff6237..a5b96cb0dc 100644 --- a/t/helper/test-dir-iterator.c +++ b/t/helper/test-dir-iterator.c @@ -4,29 +4,44 @@ #include "iterator.h" #include "dir-iterator.h" -/* Argument is a directory path to iterate over */ +/* + * usage: + * tool-test dir-iterator [--follow-symlinks] [--pedantic] directory_path + */ int cmd__dir_iterator(int argc, const char **argv) { struct strbuf path = STRBUF_INIT; struct dir_iterator *diter; + unsigned int flags = 0; + int iter_status; + + for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) { + if (strcmp(*argv, "--follow-symlinks") == 0) + flags |= DIR_ITERATOR_FOLLOW_SYMLINKS; + else if (strcmp(*argv, "--pedantic") == 0) + flags |= DIR_ITERATOR_PEDANTIC; + else + die("invalid option '%s'", *argv); + } - if (argc < 2) - die("BUG: test-dir-iterator needs one argument"); - - strbuf_add(&path, argv[1], strlen(argv[1])); + if (!*argv || argc != 1) + die("dir-iterator needs exactly one non-option argument"); - diter = dir_iterator_begin(path.buf); + strbuf_add(&path, *argv, strlen(*argv)); + diter = dir_iterator_begin(path.buf, flags); if (!diter) { printf("dir_iterator_begin failure: %d\n", errno); exit(EXIT_FAILURE); } - while (dir_iterator_advance(diter) == ITER_OK) { + while ((iter_status = dir_iterator_advance(diter)) == ITER_OK) { if (S_ISDIR(diter->st.st_mode)) printf("[d] "); else if (S_ISREG(diter->st.st_mode)) printf("[f] "); + else if (S_ISLNK(diter->st.st_mode)) + printf("[s] "); else printf("[?] "); @@ -34,5 +49,10 @@ int cmd__dir_iterator(int argc, const char **argv) diter->path.buf); } + if (iter_status != ITER_DONE) { + printf("dir_iterator_advance failure\n"); + return 1; + } + return 0; } diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh index c739ed7911..8f996a31fa 100755 --- a/t/t0066-dir-iterator.sh +++ b/t/t0066-dir-iterator.sh @@ -65,4 +65,99 @@ test_expect_success 'begin should fail upon non directory paths' ' test_cmp expected-non-dir-output actual-non-dir-output ' +test_expect_success POSIXPERM,SANITY 'advance should not fail on errors by default' ' + cat >expected-no-permissions-output <<-EOF && + [d] (a) [a] ./dir3/a + EOF + + mkdir -p dir3/a && + > dir3/a/b && + chmod 0 dir3/a && + + test-tool dir-iterator ./dir3 >actual-no-permissions-output && + test_cmp expected-no-permissions-output actual-no-permissions-output && + chmod 755 dir3/a && + rm -rf dir3 +' + +test_expect_success POSIXPERM,SANITY 'advance should fail on errors, w/ pedantic flag' ' + cat >expected-no-permissions-pedantic-output <<-EOF && + [d] (a) [a] ./dir3/a + dir_iterator_advance failure + EOF + + mkdir -p dir3/a && + > dir3/a/b && + chmod 0 dir3/a && + + test_must_fail test-tool dir-iterator --pedantic ./dir3 \ + >actual-no-permissions-pedantic-output && + test_cmp expected-no-permissions-pedantic-output \ + actual-no-permissions-pedantic-output && + chmod 755 dir3/a && + rm -rf dir3 +' + +test_expect_success SYMLINKS 'setup dirs with symlinks' ' + mkdir -p dir4/a && + mkdir -p dir4/b/c && + >dir4/a/d && + ln -s d dir4/a/e && + ln -s ../b dir4/a/f && + + mkdir -p dir5/a/b && + mkdir -p dir5/a/c && + ln -s ../c dir5/a/b/d && + ln -s ../ dir5/a/b/e && + ln -s ../../ dir5/a/b/f +' + +test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' ' + cat >expected-no-follow-sorted-output <<-EOF && + [d] (a) [a] ./dir4/a + [d] (b) [b] ./dir4/b + [d] (b/c) [c] ./dir4/b/c + [f] (a/d) [d] ./dir4/a/d + [s] (a/e) [e] ./dir4/a/e + [s] (a/f) [f] ./dir4/a/f + EOF + + test-tool dir-iterator ./dir4 >out && + sort actual-no-follow-sorted-output && + + test_cmp expected-no-follow-sorted-output actual-no-follow-sorted-output +' + +test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag' ' + cat >expected-follow-sorted-output <<-EOF && + [d] (a) [a] ./dir4/a + [d] (a/f) [f] ./dir4/a/f + [d] (a/f/c) [c] ./dir4/a/f/c + [d] (b) [b] ./dir4/b + [d] (b/c) [c] ./dir4/b/c + [f] (a/d) [d] ./dir4/a/d + [f] (a/e) [e] ./dir4/a/e + EOF + + test-tool dir-iterator --follow-symlinks ./dir4 >out && + sort actual-follow-sorted-output && + + test_cmp expected-follow-sorted-output actual-follow-sorted-output +' + + +test_expect_success SYMLINKS 'dir-iterator should ignore recursive symlinks w/ follow flag' ' + cat >expected-rec-symlinks-sorted-output <<-EOF && + [d] (a) [a] ./dir5/a + [d] (a/b) [b] ./dir5/a/b + [d] (a/b/d) [d] ./dir5/a/b/d + [d] (a/c) [c] ./dir5/a/c + EOF + + test-tool dir-iterator --follow-symlinks ./dir5 >out && + sort actual-rec-symlinks-sorted-output && + + test_cmp expected-rec-symlinks-sorted-output actual-rec-symlinks-sorted-output +' + test_done From patchwork Tue Jun 18 23:27:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003119 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B2B414B6 for ; Tue, 18 Jun 2019 23:29:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2CB1028AC4 for ; Tue, 18 Jun 2019 23:29:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2102A28B2D; Tue, 18 Jun 2019 23:29:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AB0CE28AC4 for ; Tue, 18 Jun 2019 23:29:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729304AbfFRX3b (ORCPT ); Tue, 18 Jun 2019 19:29:31 -0400 Received: from mail-qt1-f195.google.com ([209.85.160.195]:34788 "EHLO mail-qt1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3b (ORCPT ); Tue, 18 Jun 2019 19:29:31 -0400 Received: by mail-qt1-f195.google.com with SMTP id m29so17704811qtu.1 for ; Tue, 18 Jun 2019 16:29:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=j7VvYjbUk4xO+XEtU2tDr9QV4gBrLPLujUfwSSr9xw4=; b=tmJdhZwVWAsoKvr8DXerLLstJzZHsxWCmVt6AvMCtVVWsiYjo2HcCQO7ZKMowSQf4m aGtBx1afGcqLC7wxGE4SLL5TahRWL0Wh20n0JcJbO2w65Xe0CLiGLHz83jB/NN8sUMrI kj83tgUnzJkKcGwjobK6doactoUAfcnQh/vEOUxnlHHZXwkXX/o9YBpNZ9dddxuJP4CF +XiVdJXKHSrlRKUNShttXQAcjOmCxIzn31bJaM6k9mTeAEybZruqoqhkvl7V1FeQQD4d XUBQF4eKsU6gYXFoNtj2EzKfGrVoxlVHDJfedtb+euqMj93l5f8KZP0tcUIpph8uP7zJ N1uw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=j7VvYjbUk4xO+XEtU2tDr9QV4gBrLPLujUfwSSr9xw4=; b=tlrdRXJgtXyOpmJvR8FTu0JFe+sg2EhrqGLwkFoAKoSnSO9cYwNQWKn0cCJDKWF5tA VoABctVdOYvr0kVpQzPMcG9DtbGAYmJ6TqrhNopZ8fdkhoQ4n7w7HQj5fDjW2sJ0nZFI t4kzcrPmEXoTfuOrqHYXTBJkHpaRUGBQ0QPXY1GlftZ1/Y5TabbDLOPBDbBC9icTMK5C r0RG2i3m/rdWoqrohm9PhvF90gdFZwdQPA0ZiOkRE1flzBDtlsyHOdFbf7SdVgq+ajOU 3FnVIOQPKO9FMw3vPUvtwOpqAYwcJkbExu1qlvcHO+1VZPu/RdP9dxnZOzeYpjT0/nLZ /aBQ== X-Gm-Message-State: APjAAAW8uAgqa7+pT0uxGZJCM48nnTWQG7adugzDakvgdo+X74KuB7/R b8mXEgFrtAlOtKMb63Fpg0oOZdnB4a4= X-Google-Smtp-Source: APXvYqw/ryL+OBrOIERDZ84UBAT0De5rlYBCX38hFfwjk/udEpOLfk9fsWEw09EYBBpxd0YaVQ/1gg== X-Received: by 2002:ac8:c0e:: with SMTP id k14mr59681480qti.72.1560900570454; Tue, 18 Jun 2019 16:29:30 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.27 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:30 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Jeff King , Junio C Hamano Subject: [GSoC][PATCH v7 07/10] clone: copy hidden paths at local clone Date: Tue, 18 Jun 2019 20:27:44 -0300 Message-Id: <5dc1cb8f840dcb01692d54183356b5c9c8ae169f.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Make the copy_or_link_directory function no longer skip hidden directories. This function, used to copy .git/objects, currently skips all hidden directories but not hidden files, which is an odd behaviour. The reason for that could be unintentional: probably the intention was to skip '.' and '..' only but it ended up accidentally skipping all directories starting with '.'. Besides being more natural, the new behaviour is more permissive to the user. Also adjust tests to reflect this behaviour change. Signed-off-by: Matheus Tavares Signed-off-by: Ævar Arnfjörð Bjarmason Co-authored-by: Ævar Arnfjörð Bjarmason --- builtin/clone.c | 2 +- t/t5604-clone-reference.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/builtin/clone.c b/builtin/clone.c index 4a0a2455a7..9dd083e34d 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -430,7 +430,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, continue; } if (S_ISDIR(buf.st_mode)) { - if (de->d_name[0] != '.') + if (!is_dot_or_dotdot(de->d_name)) copy_or_link_directory(src, dest, src_repo, src_baselen); continue; diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 0800c3853f..c3998f2f9e 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -247,16 +247,25 @@ test_expect_success 'clone a repo with garbage in objects/*' ' done && find S-* -name "*some*" | sort >actual && cat >expected <<-EOF && + S--dissociate/.git/objects/.some-hidden-dir + S--dissociate/.git/objects/.some-hidden-dir/.some-dot-file + S--dissociate/.git/objects/.some-hidden-dir/some-file S--dissociate/.git/objects/.some-hidden-file S--dissociate/.git/objects/some-dir S--dissociate/.git/objects/some-dir/.some-dot-file S--dissociate/.git/objects/some-dir/some-file S--dissociate/.git/objects/some-file + S--local/.git/objects/.some-hidden-dir + S--local/.git/objects/.some-hidden-dir/.some-dot-file + S--local/.git/objects/.some-hidden-dir/some-file S--local/.git/objects/.some-hidden-file S--local/.git/objects/some-dir S--local/.git/objects/some-dir/.some-dot-file S--local/.git/objects/some-dir/some-file S--local/.git/objects/some-file + S--no-hardlinks/.git/objects/.some-hidden-dir + S--no-hardlinks/.git/objects/.some-hidden-dir/.some-dot-file + S--no-hardlinks/.git/objects/.some-hidden-dir/some-file S--no-hardlinks/.git/objects/.some-hidden-file S--no-hardlinks/.git/objects/some-dir S--no-hardlinks/.git/objects/some-dir/.some-dot-file From patchwork Tue Jun 18 23:27:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003121 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 83B831395 for ; Tue, 18 Jun 2019 23:29:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6FD0D28901 for ; Tue, 18 Jun 2019 23:29:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6382728ACA; Tue, 18 Jun 2019 23:29:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0A16028901 for ; Tue, 18 Jun 2019 23:29:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729334AbfFRX3i (ORCPT ); Tue, 18 Jun 2019 19:29:38 -0400 Received: from mail-qt1-f195.google.com ([209.85.160.195]:40048 "EHLO mail-qt1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3h (ORCPT ); Tue, 18 Jun 2019 19:29:37 -0400 Received: by mail-qt1-f195.google.com with SMTP id a15so17672378qtn.7 for ; Tue, 18 Jun 2019 16:29:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DPoy5SCr9H6wbbntCXImFSyMCGfsAC0sldlgcwIwbqI=; b=DR00RpbYwjioziuqgkmSmtG4jB91B+RmyewuvSo3YOGP870OoOd2tM9eE1XkJ3pIWN BSLkXSq9JkGgQF/yRNDiSnKumKlIFXwT0ghcGXVvvCJQbjPcBNAfUgJJ1sdZBd+lApCE /Q13SrrbVT9388oaHvxiumLrkZE3lhMjWkH7WW2UVT1t5ytjT606q3NL/i5XJUd8f21d e+qcvFsFw6hQUjGaAWp5N4Prcs7zQRCg1L+Kb+XorPtqulewsij8CxU3Wwp1GQcdZUJb 7hQBd0OE80HDasxoxV8Ofbg28ivqfQ5qT4SYszDL4pdY0fjarWbzSrEegZfZt2+r8s7o n2VQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DPoy5SCr9H6wbbntCXImFSyMCGfsAC0sldlgcwIwbqI=; b=bqiFh84SDXdeIxfWGDpicrIVVa3EsSNogjx0rqWjeBmv5+BsTqoHDQtVPgCRAVs9zb kZmruog4MYl3DXlMlXiPZFc4b2XfNUjfEYq1JNWOKE8Q9xSmWdEUeQZIZWZDw1IzKtsw Fg11NnAg73WXKzu9jk1AemXOcbdYNN6WP7NLy3/p1gpT/7ZRWFAtkHpAq9LfWpvJdwd6 o21qo6odEie4kL5YaejBbvShwOHT20oF9KB+YDAE9NUCDelcuF5PLkzdmHXCFubNGAi5 aKFEJ+t9c12VZsw6YdPFRgeIPwQ3l8koZJmwvJgdIyepgQ+Aa1rzoTjDtjLfSbAwjKlU VdDA== X-Gm-Message-State: APjAAAWfGAv8Bppc3TOFF0q7QrkuhvsTKvtlIuvA7f+rgQSrEUdohQI9 DQBv7xotEr4c9FWfFf/ojgpOJYfiGOM= X-Google-Smtp-Source: APXvYqzPt9iK79IoKLI4OF41XRju+cCNLvApKONArjt2f1H1z4Zg1KbyCH8F+bSwFCZUVqVOvufW/g== X-Received: by 2002:a0c:add8:: with SMTP id x24mr30691806qvc.167.1560900576898; Tue, 18 Jun 2019 16:29:36 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.33 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:36 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Jeff King , Junio C Hamano Subject: [GSoC][PATCH v7 08/10] clone: extract function from copy_or_link_directory Date: Tue, 18 Jun 2019 20:27:45 -0300 Message-Id: <8a3f7103366cef36d1c505251d89d64cdf274889.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Extract dir creation code snippet from copy_or_link_directory to its own function named mkdir_if_missing. This change will help to remove copy_or_link_directory's explicit recursion, which will be done in a following patch. Also makes the code more readable. Signed-off-by: Matheus Tavares --- builtin/clone.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 9dd083e34d..96566c1bab 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -394,6 +394,21 @@ static void copy_alternates(struct strbuf *src, const char *src_repo) fclose(in); } +static void mkdir_if_missing(const char *pathname, mode_t mode) +{ + struct stat st; + + if (!mkdir(pathname, mode)) + return; + + if (errno != EEXIST) + die_errno(_("failed to create directory '%s'"), pathname); + else if (stat(pathname, &st)) + die_errno(_("failed to stat '%s'"), pathname); + else if (!S_ISDIR(st.st_mode)) + die(_("%s exists and is not a directory"), pathname); +} + static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, const char *src_repo, int src_baselen) { @@ -406,14 +421,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, if (!dir) die_errno(_("failed to open '%s'"), src->buf); - if (mkdir(dest->buf, 0777)) { - if (errno != EEXIST) - die_errno(_("failed to create directory '%s'"), dest->buf); - else if (stat(dest->buf, &buf)) - die_errno(_("failed to stat '%s'"), dest->buf); - else if (!S_ISDIR(buf.st_mode)) - die(_("%s exists and is not a directory"), dest->buf); - } + mkdir_if_missing(dest->buf, 0777); strbuf_addch(src, '/'); src_len = src->len; From patchwork Tue Jun 18 23:27:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003123 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9E4E14B6 for ; Tue, 18 Jun 2019 23:29:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A989D28901 for ; Tue, 18 Jun 2019 23:29:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9D2E828B2D; Tue, 18 Jun 2019 23:29:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E14528AC4 for ; Tue, 18 Jun 2019 23:29:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729349AbfFRX3n (ORCPT ); Tue, 18 Jun 2019 19:29:43 -0400 Received: from mail-qt1-f193.google.com ([209.85.160.193]:35970 "EHLO mail-qt1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3n (ORCPT ); Tue, 18 Jun 2019 19:29:43 -0400 Received: by mail-qt1-f193.google.com with SMTP id p15so17696450qtl.3 for ; Tue, 18 Jun 2019 16:29:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fu0ZaITrLpRzB5mU/BeP7aSo/y6+b2a/VCRECbfe91I=; b=h3wUSK8me4YYLUU6UKJgPmGcJoZX0hZcgWAHreeNS+/aoWcDLHGE7iSvsGKm3aYhSx RruZ4kSipvYEYtkLikURNHD5c5AfC2Y5Tfw0k8wWCou/XHo1+7FRiIxaRFj/N+0AHDkg lQrzzdfGEyHnEh6ofBab7ZOcJTPPkwfCwjBxnjggaG5XD26yLmArXwys1yvIi7+jYxNT mwyd8vN/FJkcYMidn//pe1/onyJ54pKlhbSnwzVNCAfRSSjBLseppD0IO+Y/9kOjLrny cwnGcnBsOMMk2dCivKm/ZRer+47cs9Jqo9J8Ffw/OpvBovr1RFdjcglTd3YBmHowM4VQ yXRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fu0ZaITrLpRzB5mU/BeP7aSo/y6+b2a/VCRECbfe91I=; b=qWq2Bu3DVquiqk8cPWEleWv5/j1Yh0WyGrlo4WuTXn1f2cNHIWLEpk+DVcJUrmr3dz LyJkz5mBtsHZXnu3GiUNWs67Mlo3yjKKN16P0x2V1NddkQUnOMq2qKo3LJXHqjfKkN65 DgH9bzUqh91NRiCwLEksjmOaMxE+yGIyvR9ceptnjlKhvWJCZwOFpTPj/8qeG7JshFX4 8YsMvLY7mAVYu4JJJQiFp8gdJSRpwk/ZaJsyluN3WelaLiOVH1dsJ4UyvZ9eQJTVYPro zujBT23k+zd3WR6r5ls2R7QHvZhOyDvRMaTli3poJkmUqRFhdZhJPG+V7RbdQcVj8arh mfeQ== X-Gm-Message-State: APjAAAXBe349JpFysKje5VvFNG38CR2NeLWq19aieFAgi7KfDQU5AFTk YYRH6N5I3KTplT85u0tnm9t3QZUsNJo= X-Google-Smtp-Source: APXvYqzrHcs8CylTXfFySeAKJDCyd5AAZr0kQUgAp7o60Q28n8HsUmd+42K0PNkmke9u9s/pZXrWcg== X-Received: by 2002:ac8:82a:: with SMTP id u39mr45966759qth.370.1560900581616; Tue, 18 Jun 2019 16:29:41 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.38 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:41 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Junio C Hamano , Jeff King Subject: [GSoC][PATCH v7 09/10] clone: use dir-iterator to avoid explicit dir traversal Date: Tue, 18 Jun 2019 20:27:46 -0300 Message-Id: <47ccb3be1a92a30cbe084730e4a139f049da1351.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace usage of opendir/readdir/closedir API to traverse directories recursively, at copy_or_link_directory function, by the dir-iterator API. This simplifies the code and avoids recursive calls to copy_or_link_directory. This process also makes copy_or_link_directory call die() in case of an error on readdir or stat inside dir_iterator_advance. Previously it would just print a warning for errors on stat and ignore errors on readdir, which isn't nice because a local git clone could succeed even though the .git/objects copy didn't fully succeed. Also, with the dir-iterator API, recursive symlinks will be detected and skipped. This is another behavior improvement, since the current version would continue to copy the same content over and over until stat() returned an ELOOP error. Signed-off-by: Matheus Tavares --- builtin/clone.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 96566c1bab..47cb4a2a8e 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -23,6 +23,8 @@ #include "transport.h" #include "strbuf.h" #include "dir.h" +#include "dir-iterator.h" +#include "iterator.h" #include "sigchain.h" #include "branch.h" #include "remote.h" @@ -410,42 +412,39 @@ static void mkdir_if_missing(const char *pathname, mode_t mode) } static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, - const char *src_repo, int src_baselen) + const char *src_repo) { - struct dirent *de; - struct stat buf; int src_len, dest_len; - DIR *dir; - - dir = opendir(src->buf); - if (!dir) - die_errno(_("failed to open '%s'"), src->buf); + struct dir_iterator *iter; + int iter_status; + unsigned int flags; mkdir_if_missing(dest->buf, 0777); + flags = DIR_ITERATOR_PEDANTIC | DIR_ITERATOR_FOLLOW_SYMLINKS; + iter = dir_iterator_begin(src->buf, flags); + + if (!iter) + die_errno(_("failed to start iterator over '%s'"), src->buf); + strbuf_addch(src, '/'); src_len = src->len; strbuf_addch(dest, '/'); dest_len = dest->len; - while ((de = readdir(dir)) != NULL) { + while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) { strbuf_setlen(src, src_len); - strbuf_addstr(src, de->d_name); + strbuf_addstr(src, iter->relative_path); strbuf_setlen(dest, dest_len); - strbuf_addstr(dest, de->d_name); - if (stat(src->buf, &buf)) { - warning (_("failed to stat %s\n"), src->buf); - continue; - } - if (S_ISDIR(buf.st_mode)) { - if (!is_dot_or_dotdot(de->d_name)) - copy_or_link_directory(src, dest, - src_repo, src_baselen); + strbuf_addstr(dest, iter->relative_path); + + if (S_ISDIR(iter->st.st_mode)) { + mkdir_if_missing(dest->buf, 0777); continue; } /* Files that cannot be copied bit-for-bit... */ - if (!strcmp(src->buf + src_baselen, "/info/alternates")) { + if (!strcmp(iter->relative_path, "info/alternates")) { copy_alternates(src, src_repo); continue; } @@ -462,7 +461,11 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, if (copy_file_with_time(dest->buf, src->buf, 0666)) die_errno(_("failed to copy file to '%s'"), dest->buf); } - closedir(dir); + + if (iter_status != ITER_DONE) { + strbuf_setlen(src, src_len); + die(_("failed to iterate over '%s'"), src->buf); + } } static void clone_local(const char *src_repo, const char *dest_repo) @@ -480,7 +483,7 @@ static void clone_local(const char *src_repo, const char *dest_repo) get_common_dir(&dest, dest_repo); strbuf_addstr(&src, "/objects"); strbuf_addstr(&dest, "/objects"); - copy_or_link_directory(&src, &dest, src_repo, src.len); + copy_or_link_directory(&src, &dest, src_repo); strbuf_release(&src); strbuf_release(&dest); } From patchwork Tue Jun 18 23:27:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matheus Tavares X-Patchwork-Id: 11003125 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2CCE714B6 for ; Tue, 18 Jun 2019 23:29:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C9AE28901 for ; Tue, 18 Jun 2019 23:29:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1087F28ACA; Tue, 18 Jun 2019 23:29:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B7A1728901 for ; Tue, 18 Jun 2019 23:29:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729188AbfFRX3s (ORCPT ); Tue, 18 Jun 2019 19:29:48 -0400 Received: from mail-qk1-f195.google.com ([209.85.222.195]:37561 "EHLO mail-qk1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRX3s (ORCPT ); Tue, 18 Jun 2019 19:29:48 -0400 Received: by mail-qk1-f195.google.com with SMTP id d15so9760799qkl.4 for ; Tue, 18 Jun 2019 16:29:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=usp-br.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TA7qLhwVjgT7/njeUhcABACRPDG7IyBV0uSnJgIka+0=; b=OW3grMpaH4E11wreoHadPlHGG/YP31uAA1EWPqBTXpK97MXaC0R1vNWyuZMa6wk+he qJ/j8MdVuu+EX0X1LelZ4c+HC6mXnMEhxQpSO87xm9xNnb6niy4jSDRPX7ICimhtgYz9 xN8wwAwagrU+ZG97Rez6aomqwC+h6tASSJ8FX5oLXnIUk4U4i+Ir4TTx3U1VeNHUcyiA aNgk8LMur9e2RnrvQW+EIY2Q00juv1Dns6gqK29OThlHtiff0g+diZc2qDUaaLkKR/BN 1DKH58E4AwZbZSBbNvUTgqwx6LHFVzXDLerVlW7SwZDpOQJz4lTuAt0vl4wz5dfpFg0O 0ufg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TA7qLhwVjgT7/njeUhcABACRPDG7IyBV0uSnJgIka+0=; b=f55q92/cIQtXwkIwpP/IRDAox/ADuaSpFUac5Ru6aTD6SqthgpkxBNOwyIZa6td2xI mpeRY6wvJYPX3QeCXkDgmFHgfeA2i/d3nYhmGSrYqk54WDB4qfsCbBwpLaaqua0U6kMJ F8+zhWMaIU0cq0bcsPXd+RVDwiERUOhU/60hEROR4babZa4V8U4flGs+d7hCNQBXb4/s 3Aw7S794xqinpYWAF+10A774KEmsGzVnxS24rHOQkwM2xH0o3MHw8uMsV2AD6EhxDujQ gQSTxZQbzBzbAabkLzGZdM/oikIbYJ0mAJKAUgJrZSo381ig+EZAur4xGvoiQB5+5OgP +XdQ== X-Gm-Message-State: APjAAAU3qseNHLOwj4jSR33QieN0Iu8XNijyBMSFBXCg3F4GyPPM6wqK 670sggCYgdZfidBMvrmA/junDrL5ut0= X-Google-Smtp-Source: APXvYqwIR1eSp0suJleH3eynzrOIE2oTWbIIp9oOX6AKg1nVriHXQpWDz7stVvauEHcIfJ4/makKXg== X-Received: by 2002:a37:a5d5:: with SMTP id o204mr22089492qke.155.1560900587430; Tue, 18 Jun 2019 16:29:47 -0700 (PDT) Received: from mango.semfio.usp.br ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id e18sm4828997qkm.49.2019.06.18.16.29.44 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 16:29:47 -0700 (PDT) From: Matheus Tavares To: git@vger.kernel.org Cc: Thomas Gummerer , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7AgQmphcm1hc29u?= , Christian Couder , =?utf-8?b?Tmd1eeG7hW4gVGg=?= =?utf-8?b?w6FpIE5n4buNYyBEdXk=?= , =?utf-8?q?SZEDER_G?= =?utf-8?q?=C3=A1bor?= , Olga Telezhnaya , kernel-usp@googlegroups.com, Jeff King , Junio C Hamano Subject: [GSoC][PATCH v7 10/10] clone: replace strcmp by fspathcmp Date: Tue, 18 Jun 2019 20:27:47 -0300 Message-Id: <1ba1e9c395237aa34e698d5e5d2d0bbd875f6117.1560898723.git.matheus.bernardino@usp.br> X-Mailer: git-send-email 2.22.0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace the use of strcmp by fspathcmp at copy_or_link_directory, which is more permissive/friendly to case-insensitive file systems. Suggested-by: Nguyễn Thái Ngọc Duy Signed-off-by: Matheus Tavares --- builtin/clone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/clone.c b/builtin/clone.c index 47cb4a2a8e..8da696ef30 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -444,7 +444,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, } /* Files that cannot be copied bit-for-bit... */ - if (!strcmp(iter->relative_path, "info/alternates")) { + if (!fspathcmp(iter->relative_path, "info/alternates")) { copy_alternates(src, src_repo); continue; }