From 130e47d77748cf8035eeb4eb7265ea91a74a87bd Mon Sep 17 00:00:00 2001 From: Noel Cower Date: Tue, 21 Apr 2020 20:30:50 -0700 Subject: [PATCH] Add -D, -d option to control duplicate entry skipping This adds an option to skip (-D) or allow (-d) duplicate entries in the output stream. By default, duplicates are skipped (a change from mtar's prior behavior, which was to not check). --- mtar.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/mtar.go b/mtar.go index 4afba0e..67aaa43 100644 --- a/mtar.go +++ b/mtar.go @@ -90,10 +90,14 @@ // // -h | --help // When passed as the first argument, print this usage text. +// -D +// Prevent duplicate entries with the same name. (default) +// -d +// Allow duplicate entries with the same name. // -U // Do not assign user information to files. // -u -// Assign user information to files (default). +// Assign user information to files. (default) // -Fformat | -F format // Set the tar header format to use. May be one of the following // formats: @@ -151,12 +155,17 @@ func (m Matcher) matches(s string) bool { return m.rx.MatchString(s) == m.want } -var hdrFormat = tar.FormatPAX -var startupTime = time.Now() -var startupDir string -var skipSrcGlobs []Matcher -var skipDestGlobs []Matcher -var skipUserInfo bool +var ( + startupTime = time.Now() + + hdrFormat = tar.FormatPAX + startupDir string + skipSrcGlobs []Matcher + skipDestGlobs []Matcher + skipUserInfo bool + skipWritten = true + written = map[string]struct{}{} // Already-written paths +) func (p *Args) Shift() (s string, ok bool) { if ok = len(p.args) > 0; ok { @@ -224,10 +233,14 @@ control archive creation: -h | --help When passed as the first argument, print this usage text. + -D + Prevent duplicate entries with the same name. (default) + -d + Allow duplicate entries with the same name. -U Do not assign user information to files. -u - Assign user information to files (default). + Assign user information to files. (default) -Fformat | -F format Set the tar header format to use. May be one of the following formats: @@ -330,6 +343,11 @@ func main() { want := s[1] == 'o' skipDestGlobs = append(skipDestGlobs, Matcher{rx: regexp.MustCompile(s[2:]), want: want}) + // -D Skip duplicate header entries. + // -d Allow duplicate header entries. + case s == "-D", s == "-d": + skipWritten = s == "-D" + // -U Do not collect user info for headers unless explicitly set // -u Enable collection. case s == "-U", s == "-u": @@ -484,6 +502,7 @@ func addFile(w *tar.Writer, src, dest string, opts *FileOpts, allowRecursive boo } failOnError("write header: "+hdr.Name, w.WriteHeader(hdr)) + written[hdr.Name] = struct{}{} addDirOnly: if st.Mode().IsDir() { @@ -543,6 +562,9 @@ func failOnError(prefix string, err error) { } func shouldSkip(set []Matcher, s string) bool { + if _, seen := written[s]; seen && skipWritten { + return seen + } for _, m := range set { if !m.matches(s) { return true -- 2.45.2