diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2019-02-14 00:31:48 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2019-02-14 00:39:24 -0500 |
commit | 02beb30bf863d2b135e0b1750b1628857776891a (patch) | |
tree | 733144b59cba1681288834ab780877a5688969db | |
parent | f5cf7bc69f74a5006720172c3a7ecc9b0d9da4b2 (diff) |
more
-rw-r--r-- | README.md | 17 | ||||
-rw-r--r-- | fi-filefilter/main.go | 30 | ||||
-rw-r--r-- | fi-filelist/main.go | 18 | ||||
-rw-r--r-- | fi-prune-empty/main.go | 127 |
4 files changed, 154 insertions, 38 deletions
@@ -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 } |