summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--tar/bsdtar.112
-rw-r--r--tar/bsdtar.c31
-rw-r--r--tar/bsdtar.h1
-rw-r--r--tar/cmdline.c1
-rw-r--r--tar/test/CMakeLists.txt1
-rw-r--r--tar/test/test_option_exclude_vcs.c230
7 files changed, 277 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 186126be..5cded0e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -995,6 +995,7 @@ bsdtar_test_SOURCES= \
tar/test/test_option_b.c \
tar/test/test_option_b64encode.c \
tar/test/test_option_exclude.c \
+ tar/test/test_option_exclude_vcs.c \
tar/test/test_option_fflags.c \
tar/test/test_option_gid_gname.c \
tar/test/test_option_grzip.c \
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 132e1145..4c0fe818 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -204,6 +204,18 @@ Do not process files or directories that match the
specified pattern.
Note that exclusions take precedence over patterns or filenames
specified on the command line.
+.It Fl Fl exclude-vcs
+Do not process files or directories internally used by the
+version control systems
+.Sq CVS ,
+.Sq RCS ,
+.Sq SCCS ,
+.Sq SVN ,
+.Sq Arch ,
+.Sq Bazaar ,
+.Sq Mercurial
+and
+.Sq Darcs .
.It Fl Fl fflags
(c, r, u, x modes only)
Archive or extract file flags. This is the reverse of
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index e70b3929..280a0a16 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -129,6 +129,28 @@ static void version(void) __LA_DEAD;
(ARCHIVE_EXTRACT_SECURE_SYMLINKS \
| ARCHIVE_EXTRACT_SECURE_NODOTDOT)
+static char const * const vcs_files[] = {
+ /* CVS */
+ "CVS", ".cvsignore",
+ /* RCS */
+ "RCS",
+ /* SCCS */
+ "SCCS",
+ /* SVN */
+ ".svn",
+ /* git */
+ ".git", ".gitignore", ".gitattributes", ".gitmodules",
+ /* Arch */
+ ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update",
+ /* Bazaar */
+ ".bzr", ".bzrignore", ".bzrtags",
+ /* Mercurial */
+ ".hg", ".hgignore", ".hgtags",
+ /* darcs */
+ "_darcs",
+ NULL
+};
+
int
main(int argc, char **argv)
{
@@ -318,6 +340,15 @@ main(int argc, char **argv)
lafe_errc(1, 0,
"Couldn't exclude %s\n", bsdtar->argument);
break;
+ case OPTION_EXCLUDE_VCS: /* GNU tar */
+ for(t=0; vcs_files[t]; t++) {
+ if (archive_match_exclude_pattern(
+ bsdtar->matching,
+ vcs_files[t]) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Couldn't "
+ "exclude %s\n", vcs_files[t]);
+ }
+ break;
case OPTION_FFLAGS:
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS;
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index 543a228c..c61d568f 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -135,6 +135,7 @@ enum {
OPTION_CHROOT,
OPTION_CLEAR_NOCHANGE_FFLAGS,
OPTION_EXCLUDE,
+ OPTION_EXCLUDE_VCS,
OPTION_FFLAGS,
OPTION_FORMAT,
OPTION_GID,
diff --git a/tar/cmdline.c b/tar/cmdline.c
index 66cf4c2d..21558e12 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -85,6 +85,7 @@ static const struct bsdtar_option {
{ "disable-copyfile", 0, OPTION_NO_MAC_METADATA },
{ "exclude", 1, OPTION_EXCLUDE },
{ "exclude-from", 1, 'X' },
+ { "exclude-vcs", 0, OPTION_EXCLUDE_VCS },
{ "extract", 0, 'x' },
{ "fast-read", 0, 'q' },
{ "fflags", 0, OPTION_FFLAGS },
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index d7de42d6..459d9dcb 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -40,6 +40,7 @@ IF(ENABLE_TAR AND ENABLE_TEST)
test_option_b.c
test_option_b64encode.c
test_option_exclude.c
+ test_option_exclude_vcs.c
test_option_fflags.c
test_option_gid_gname.c
test_option_grzip.c
diff --git a/tar/test/test_option_exclude_vcs.c b/tar/test/test_option_exclude_vcs.c
new file mode 100644
index 00000000..20215113
--- /dev/null
+++ b/tar/test/test_option_exclude_vcs.c
@@ -0,0 +1,230 @@
+/*-
+ * Copyright (c) 2019 Martin Matuska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_exclude_vcs)
+{
+ assertMakeDir("in", 0755);
+ assertChdir("in");
+ assertMakeFile("file", 0644, "");
+ assertMakeDir("dir", 0755);
+ assertMakeDir("CVS", 0755);
+ assertMakeFile("CVS/fileattr", 0644, "");
+ assertMakeFile(".cvsignore", 0644, "");
+ assertMakeDir("RCS", 0755);
+ assertMakeFile("RCS/somefile", 0655, "");
+ assertMakeDir("SCCS", 0755);
+ assertMakeFile("SCCS/somefile", 0655, "");
+ assertMakeDir(".svn", 0755);
+ assertMakeFile(".svn/format", 0655, "");
+ assertMakeDir(".git", 0755);
+ assertMakeFile(".git/config", 0655, "");
+ assertMakeFile(".gitignore", 0644, "");
+ assertMakeFile(".gitattributes", 0644, "");
+ assertMakeFile(".gitmodules", 0644, "");
+ assertMakeDir(".arch-ids", 0755);
+ assertMakeFile(".arch-ids/somefile", 0644, "");
+ assertMakeDir("{arch}", 0755);
+ assertMakeFile("{arch}/somefile", 0644, "");
+ assertMakeFile("=RELEASE-ID", 0644, "");
+ assertMakeFile("=meta-update", 0644, "");
+ assertMakeFile("=update", 0644, "");
+ assertMakeDir(".bzr", 0755);
+ assertMakeDir(".bzr/checkout", 0755);
+ assertMakeFile(".bzrignore", 0644, "");
+ assertMakeFile(".bzrtags", 0644, "");
+ assertMakeDir(".hg", 0755);
+ assertMakeFile(".hg/dirstate", 0644, "");
+ assertMakeFile(".hgignore", 0644, "");
+ assertMakeFile(".hgtags", 0644, "");
+ assertMakeDir("_darcs", 0755);
+ assertMakeFile("_darcs/format", 0644, "");
+ assertChdir("..");
+
+ assertEqualInt(0, systemf("%s -c -C in -f included.tar .", testprog));
+ assertEqualInt(0,
+ systemf("%s -c --exclude-vcs -C in -f excluded.tar .", testprog));
+
+ /* No flags, archive with vcs files */
+ assertMakeDir("vcs-noexclude", 0755);
+ assertEqualInt(0, systemf("%s -x -C vcs-noexclude -f included.tar",
+ testprog));
+ assertChdir("vcs-noexclude");
+ assertFileExists("file");
+ assertIsDir("dir", 0755);
+ assertIsDir("CVS", 0755);
+ assertFileExists("CVS/fileattr");
+ assertFileExists(".cvsignore");
+ assertIsDir("RCS", 0755);
+ assertFileExists("RCS/somefile");
+ assertIsDir("SCCS", 0755);
+ assertFileExists("SCCS/somefile");
+ assertIsDir(".svn", 0755);
+ assertFileExists(".svn/format");
+ assertIsDir(".git", 0755);
+ assertFileExists(".git/config");
+ assertFileExists(".gitignore");
+ assertFileExists(".gitattributes");
+ assertFileExists(".gitmodules");
+ assertIsDir(".arch-ids", 0755);
+ assertFileExists(".arch-ids/somefile");
+ assertIsDir("{arch}", 0755);
+ assertFileExists("{arch}/somefile");
+ assertFileExists("=RELEASE-ID");
+ assertFileExists("=meta-update");
+ assertFileExists("=update");
+ assertIsDir(".bzr", 0755);
+ assertIsDir(".bzr/checkout", 0755);
+ assertFileExists(".bzrignore");
+ assertFileExists(".bzrtags");
+ assertIsDir(".hg", 0755);
+ assertFileExists(".hg/dirstate");
+ assertFileExists(".hgignore");
+ assertFileExists(".hgtags");
+ assertIsDir("_darcs", 0755);
+ assertFileExists("_darcs/format");
+ assertChdir("..");
+
+ /* --exclude-vcs, archive with vcs files */
+ assertMakeDir("vcs-exclude", 0755);
+ assertEqualInt(0,
+ systemf("%s -x --exclude-vcs -C vcs-exclude -f included.tar", testprog));
+ assertChdir("vcs-exclude");
+ assertFileExists("file");
+ assertIsDir("dir", 0755);
+ assertFileNotExists("CVS");
+ assertFileNotExists("CVS/fileattr");
+ assertFileNotExists(".cvsignore");
+ assertFileNotExists("RCS");
+ assertFileNotExists("RCS/somefile");
+ assertFileNotExists("SCCS");
+ assertFileNotExists("SCCS/somefile");
+ assertFileNotExists(".svn");
+ assertFileNotExists(".svn/format");
+ assertFileNotExists(".git");
+ assertFileNotExists(".git/config");
+ assertFileNotExists(".gitignore");
+ assertFileNotExists(".gitattributes");
+ assertFileNotExists(".gitmodules");
+ assertFileNotExists(".arch-ids");
+ assertFileNotExists(".arch-ids/somefile");
+ assertFileNotExists("{arch}");
+ assertFileNotExists("{arch}/somefile");
+ assertFileNotExists("=RELEASE-ID");
+ assertFileNotExists("=meta-update");
+ assertFileNotExists("=update");
+ assertFileNotExists(".bzr");
+ assertFileNotExists(".bzr/checkout");
+ assertFileNotExists(".bzrignore");
+ assertFileNotExists(".bzrtags");
+ assertFileNotExists(".hg");
+ assertFileNotExists(".hg/dirstate");
+ assertFileNotExists(".hgignore");
+ assertFileNotExists(".hgtags");
+ assertFileNotExists("_darcs");
+ assertFileNotExists("_darcs/format");
+ assertChdir("..");
+
+ /* --exclude-vcs, archive without vcs files */
+ assertMakeDir("novcs-exclude", 0755);
+ assertEqualInt(0,
+ systemf("%s -x --exclude-vcs -C novcs-exclude -f excluded.tar",
+ testprog));
+ assertChdir("novcs-exclude");
+ assertFileExists("file");
+ assertIsDir("dir", 0755);
+ assertFileNotExists("CVS");
+ assertFileNotExists("CVS/fileattr");
+ assertFileNotExists(".cvsignore");
+ assertFileNotExists("RCS");
+ assertFileNotExists("RCS/somefile");
+ assertFileNotExists("SCCS");
+ assertFileNotExists("SCCS/somefile");
+ assertFileNotExists(".svn");
+ assertFileNotExists(".svn/format");
+ assertFileNotExists(".git");
+ assertFileNotExists(".git/config");
+ assertFileNotExists(".gitignore");
+ assertFileNotExists(".gitattributes");
+ assertFileNotExists(".gitmodules");
+ assertFileNotExists(".arch-ids");
+ assertFileNotExists(".arch-ids/somefile");
+ assertFileNotExists("{arch}");
+ assertFileNotExists("{arch}/somefile");
+ assertFileNotExists("=RELEASE-ID");
+ assertFileNotExists("=meta-update");
+ assertFileNotExists("=update");
+ assertFileNotExists(".bzr");
+ assertFileNotExists(".bzr/checkout");
+ assertFileNotExists(".bzrignore");
+ assertFileNotExists(".bzrtags");
+ assertFileNotExists(".hg");
+ assertFileNotExists(".hg/dirstate");
+ assertFileNotExists(".hgignore");
+ assertFileNotExists(".hgtags");
+ assertFileNotExists("_darcs");
+ assertFileNotExists("_darcs/format");
+ assertChdir("..");
+
+ /* No flags, archive without vcs files */
+ assertMakeDir("novcs-noexclude", 0755);
+ assertEqualInt(0,
+ systemf("%s -x -C novcs-noexclude -f excluded.tar", testprog));
+ assertChdir("novcs-noexclude");
+ assertFileExists("file");
+ assertIsDir("dir", 0755);
+ assertFileNotExists("CVS");
+ assertFileNotExists("CVS/fileattr");
+ assertFileNotExists(".cvsignore");
+ assertFileNotExists("RCS");
+ assertFileNotExists("RCS/somefile");
+ assertFileNotExists("SCCS");
+ assertFileNotExists("SCCS/somefile");
+ assertFileNotExists(".svn");
+ assertFileNotExists(".svn/format");
+ assertFileNotExists(".git");
+ assertFileNotExists(".git/config");
+ assertFileNotExists(".gitignore");
+ assertFileNotExists(".gitattributes");
+ assertFileNotExists(".gitmodules");
+ assertFileNotExists(".arch-ids");
+ assertFileNotExists(".arch-ids/somefile");
+ assertFileNotExists("{arch}");
+ assertFileNotExists("{arch}/somefile");
+ assertFileNotExists("=RELEASE-ID");
+ assertFileNotExists("=meta-update");
+ assertFileNotExists("=update");
+ assertFileNotExists(".bzr");
+ assertFileNotExists(".bzr/checkout");
+ assertFileNotExists(".bzrignore");
+ assertFileNotExists(".bzrtags");
+ assertFileNotExists(".hg");
+ assertFileNotExists(".hg/dirstate");
+ assertFileNotExists(".hgignore");
+ assertFileNotExists(".hgtags");
+ assertFileNotExists("_darcs");
+ assertFileNotExists("_darcs/format");
+}