summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2019-02-14 00:31:48 -0500
committerLuke Shumaker <lukeshu@lukeshu.com>2019-02-14 00:39:24 -0500
commit02beb30bf863d2b135e0b1750b1628857776891a (patch)
tree733144b59cba1681288834ab780877a5688969db
parentf5cf7bc69f74a5006720172c3a7ecc9b0d9da4b2 (diff)
more
-rw-r--r--README.md17
-rw-r--r--fi-filefilter/main.go30
-rw-r--r--fi-filelist/main.go18
-rw-r--r--fi-prune-empty/main.go127
4 files changed, 154 insertions, 38 deletions
diff --git a/README.md b/README.md
index 2b7978f..4760806 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
-Commands:
+# fastimport-go-utils
+
+There are a few general-purpose commands for working with fast-import
+streams:
- `socklinex`: Like a shell pipeline, but uses AF_UNIX socket pairs
instead of pipes. This allows an easy and ergonomic way to chain
@@ -8,3 +11,15 @@ Commands:
that do not match a regexp.
- `fi-filelist`: Reads a fast-import stream, and lists all filenames
mentioned in it.
+ - `fi-prune-empty`: Prunes a fast-import stream, removing empty
+ commits and empty merges.
+
+There are also a few special-purpose commands for working with
+fast-import streams of the Arch Build System:
+
+ - `fi-pacmanlog`
+ - `fi-svntogit-to-aur`
+
+There is also a utility library:
+
+ - `git.parabola.nu/~lukeshu/fastimport-go-utils/fiutil`
diff --git a/fi-filefilter/main.go b/fi-filefilter/main.go
index 1032584..ae992ba 100644
--- a/fi-filefilter/main.go
+++ b/fi-filefilter/main.go
@@ -77,7 +77,16 @@ func filefilter(backend *libfastimport.Backend, frontend *libfastimport.Frontend
switch cmdt := cmd.(type) {
- // file commands
+ // commit //////////////////////////////////////////////
+ case libfastimport.CmdCommit:
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
+ case libfastimport.CmdCommitEnd:
+ commits++
+ status()
+
+ // file commands ///////////////////////////////////////
case libfastimport.FileModify:
filesIn++
if re.MatchString(string(cmdt.Path)) {
@@ -111,19 +120,20 @@ func filefilter(backend *libfastimport.Backend, frontend *libfastimport.Frontend
case libfastimport.FileRename:
return errors.New("unexpected \"filerename\" command: this filter requires --full-tree")
- // statistics
- case libfastimport.CmdCommitEnd:
- commits++
- status()
+ // note commands ///////////////////////////////////////
+ case libfastimport.NoteModify, libfastimport.NoteModifyInline:
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
- // regular commands
- case libfastimport.CmdBlob, libfastimport.CmdCheckpoint, libfastimport.CmdComment, libfastimport.CmdCommit, libfastimport.CmdDone, libfastimport.CmdReset, libfastimport.CmdTag:
+ // regular commands ////////////////////////////////////
+ case libfastimport.CmdBlob, libfastimport.CmdCheckpoint, libfastimport.CmdComment, libfastimport.CmdDone, libfastimport.CmdProgress, libfastimport.CmdReset, libfastimport.CmdTag:
if err := backend.Do(cmd); err != nil {
return err
}
- // special commands
- case libfastimport.CmdProgress, libfastimport.CmdOption:
+ // special commands ////////////////////////////////////
+ case libfastimport.CmdOption:
if err := backend.Do(cmd); err != nil {
return err
}
@@ -141,7 +151,7 @@ func filefilter(backend *libfastimport.Backend, frontend *libfastimport.Frontend
return err
}
default:
- return errors.Errorf("unknown feature %q", cmdt.Feature).
+ return errors.Errorf("unknown feature %q", cmdt.Feature)
}
case libfastimport.CmdCatBlob:
sha1, data, err := backend.CatBlob(cmdt)
diff --git a/fi-filelist/main.go b/fi-filelist/main.go
index 2451544..2f9e9d6 100644
--- a/fi-filelist/main.go
+++ b/fi-filelist/main.go
@@ -95,32 +95,34 @@ func filelist(frontend *libfastimport.Frontend) ([]string, error) {
case libfastimport.NoteModify:
case libfastimport.NoteModifyInline:
- case libfastimport.CmdTag:
- case libfastimport.CmdReset:
case libfastimport.CmdBlob:
case libfastimport.CmdCheckpoint:
+ case libfastimport.CmdComment:
+ case libfastimport.CmdOption:
case libfastimport.CmdProgress:
+ case libfastimport.CmdReset:
+ case libfastimport.CmdTag:
+
+ case libfastimport.CmdCatBlob, libfastimport.CmdGetMark, libfastimport.CmdLs:
+ return nil, errors.Errorf("unsupported (but known) command %T", cmd)
case libfastimport.CmdFeature:
switch cmdt.Feature {
case "date-format":
// safe to ignore
case "export-marks":
- return errors.Errorf("unsupported (but known) feature %q", cmdt.Feature).
+ return nil, errors.Errorf("unsupported (but known) feature %q", cmdt.Feature)
case "relative-marks", "no-relative-marks", "force":
// safe to ignore
case "import-marks", "import-marks-if-exists", "get-mark", "cat-blob", "ls", "notes":
- return errors.Errorf("unsupported (but known) feature %q", cmdt.Feature).
+ return nil, errors.Errorf("unsupported (but known) feature %q", cmdt.Feature)
case "done":
needDone = true
default:
- return errors.Errorf("unknown feature %q", cmdt.Feature).
+ return nil, errors.Errorf("unknown feature %q", cmdt.Feature)
}
- case libfastimport.CmdOption:
case libfastimport.CmdDone:
needDone = false
- case libfastimport.CmdComment:
-
default:
return nil, errors.Errorf("unexpected command: %[1]T(%#[1]v)", cmd)
}
diff --git a/fi-prune-empty/main.go b/fi-prune-empty/main.go
index 6f7b767..d45cc6a 100644
--- a/fi-prune-empty/main.go
+++ b/fi-prune-empty/main.go
@@ -13,21 +13,40 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// Command fi-prune-empty prunes a fast-import stream, removing empty
+// commits and empty merges.
package main
import (
"fmt"
"io"
+ "strconv"
"os"
"sort"
+ "strings"
"git.lukeshu.com/go/libfastimport"
"github.com/pkg/errors"
)
-func abort(err error) {
- fmt.Fprintln(os.Stderr, "Error:", err)
- os.Exit(1)
+func usage(w io.Writer) {
+ fmt.Fprintf(w, "Usage: git fast-export --full-tree | %s | git fast-import\n", os.Args[0])
+ fmt.Fprintf(w, "Prunes a fast-import stream, removing empty commits and empty merges\n")
+}
+
+func main() {
+ if len(os.Args) != 1 {
+ usage(os.Stderr)
+ os.Exit(2)
+ }
+
+ frontend := libfastimport.NewFrontend(os.Stdin, os.Stdin, nil)
+ backend := libfastimport.NewBackend(os.Stdout, os.Stdout, nil)
+
+ if err := prune(backend, frontend); err != nil {
+ fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err)
+ os.Exit(1)
+ }
}
type Tree []libfastimport.FileModify
@@ -48,11 +67,7 @@ func TreesEqual(a, b Tree) bool {
return true
}
-// expects --full-tree
-func main() {
- frontend := libfastimport.NewFrontend(os.Stdin, nil, nil)
- backend := libfastimport.NewBackend(os.Stdout, nil, nil)
-
+func prune(backend *libfastimport.Backend, frontend *libfastimport.Frontend) error {
replace := map[string]string{}
fixupMark := func(m string) string {
if r, ok := replace[m]; ok {
@@ -108,11 +123,12 @@ func main() {
if err == io.EOF {
break
}
- abort(err)
+ return err
}
switch cmdt := cmd.(type) {
+ // commit //////////////////////////////////////////////
case libfastimport.CmdCommit:
commitMeta = cmdt
commitFile = Tree{}
@@ -134,29 +150,102 @@ func main() {
commitMeta.From = parents[0]
commitMeta.Merge = parents[1:]
if err := backend.Do(commitMeta); err != nil {
- abort(err)
+ return err
}
if err := backend.Do(libfastimport.FileDeleteAll{}); err != nil {
- abort(err)
+ return err
}
for _, file := range commitFile {
if err := backend.Do(file); err != nil {
- abort(err)
+ return err
}
}
- case libfastimport.FileDeleteAll:
- // do nothing
+
+ // file commands ///////////////////////////////////////
case libfastimport.FileModify:
commitFile = append(commitFile, cmdt)
+ case libfastimport.FileModifyInline:
+ return errors.New("unexpected inline \"filemodify\" command; must use a mark")
+ case libfastimport.FileCopy:
+ return errors.New("unexpected \"filecopy\" command: this filter requires --full-tree")
+ case libfastimport.FileRename:
+ return errors.New("unexpected \"filerename\" command: this filter requires --full-tree")
+ case libfastimport.FileDelete:
+ return errors.New("unexpected \"filedelete\" command: this filter requires --full-tree")
+ case libfastimport.FileDeleteAll:
+ // do nothing
+
+ // note commands ///////////////////////////////////////
+ case libfastimport.NoteModify, libfastimport.NoteModifyInline:
+ return errors.Errorf("unsupported (but known) command %T", cmd)
+
+ // regular commands ////////////////////////////////////
+ case libfastimport.CmdBlob, libfastimport.CmdCheckpoint, libfastimport.CmdComment, libfastimport.CmdDone, libfastimport.CmdProgress, libfastimport.CmdReset, libfastimport.CmdTag:
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
- case libfastimport.CmdBlob, libfastimport.CmdCheckpoint, libfastimport.CmdReset, libfastimport.CmdFeature, libfastimport.CmdOption, libfastimport.CmdDone:
- err := backend.Do(cmd)
+ // special commands ////////////////////////////////////
+ case libfastimport.CmdOption:
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
+ case libfastimport.CmdFeature:
+ switch cmdt.Feature {
+ case "date-format":
+ if cmdt.Argument != "raw" {
+ return errors.Errorf("date-format=%q: only supports the %q format", cmdt.Argument, "raw")
+ }
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
+ case "export-marks", "relative-marks", "no-relative-marks", "force", "import-marks", "import-marks-if-exists", "get-mark", "cat-blob", "ls":
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
+ case "notes":
+ return errors.Errorf("unsupported (but known) command %T", cmd)
+ case "done":
+ if err := backend.Do(cmd); err != nil {
+ return err
+ }
+ default:
+ return errors.Errorf("unknown feature %q", cmdt.Feature)
+ }
+ case libfastimport.CmdCatBlob:
+ if strings.HasPrefix(cmdt.DataRef, ":") {
+ cmdt.DataRef = fixupMark(cmdt.DataRef)
+ }
+ sha1, data, err := backend.CatBlob(cmdt)
if err != nil {
- abort(err)
+ return err
+ }
+ if err := frontend.RespondCatBlob(sha1, data); err != nil {
+ return err
+ }
+ case libfastimport.CmdGetMark:
+ cmdt.Mark, _ = strconv.Atoi(fixupMark(fmt.Sprintf(":%d", cmdt.Mark))[1:])
+ sha1, err := backend.GetMark(cmdt)
+ if err != nil {
+ return err
+ }
+ if err := frontend.RespondGetMark(sha1); err != nil {
+ return err
+ }
+ case libfastimport.CmdLs:
+ if strings.HasPrefix(cmdt.DataRef, ":") {
+ cmdt.DataRef = fixupMark(cmdt.DataRef)
+ }
+ mode, dataref, path, err := backend.Ls(cmdt)
+ if err != nil {
+ return err
+ }
+ if err := frontend.RespondLs(mode, dataref, path); err != nil {
+ return err
}
- case libfastimport.CmdComment:
default:
- abort(errors.Errorf("Unexpected command: %[1]T(%#[1]v)", cmd))
+ return errors.Errorf("unexpected command: %[1]T(%#[1]v)", cmd)
}
}
+ return nil
}