From 2495e17b6c2d4323b0c989b8ef27248f29eb9548 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 15 Feb 2019 22:04:54 -0500 Subject: write fi-sponge --- README.md | 2 + fi-sponge/sponge.go | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 fi-sponge/sponge.go diff --git a/README.md b/README.md index 4760806..0dfd357 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ streams: mentioned in it. - `fi-prune-empty`: Prunes a fast-import stream, removing empty commits and empty merges. + - `fi-sponge`: Soaks up a fast-import stream, and re-emits it, + potentially with different flags. There are also a few special-purpose commands for working with fast-import streams of the Arch Build System: diff --git a/fi-sponge/sponge.go b/fi-sponge/sponge.go new file mode 100644 index 0000000..1d42143 --- /dev/null +++ b/fi-sponge/sponge.go @@ -0,0 +1,108 @@ +// Copyright 2019 Luke Shumaker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Command fi-sponge soaks up a fast-import stream, and re-emits it, +// potentially with different flags. +package main + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "syscall" +) + +func usage() { + fmt.Printf("Usage: git fast-export | %s [FAST-IMPORT-FLAGS] -- [FAST-EXPORT-FLAGS] | git fast-import\n", os.Args[0]) +} + +func main() { + var split int + for i := range os.Args { + switch os.Args[i] { + case "--": + split = i + case "-h", "--help": + usage() + os.Exit(0) + } + } + if split == 0 { + fmt.Fprintf(os.Stderr, "%s: must give a '--' argument\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Try '%s --help' for more information\n", os.Args[0]) + os.Exit(2) + } + inargs := os.Args[1:split] + outargs := os.Args[split+1:] + err := sponge(inargs, outargs) + if err != nil { + if ee, ok := err.(*exec.ExitError); ok { + ws := ee.ProcessState.Sys().(syscall.WaitStatus) + switch { + case ws.Exited(): + os.Exit(ws.ExitStatus()) + case ws.Signaled(): + os.Exit(128 + int(ws.Signal())) + } + } else { + fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) + os.Exit(255) + } + } +} + +func sponge(inargs, outargs []string) error { + tmpdir, err := ioutil.TempDir("", filepath.Base(os.Args[0])+".") + if err != nil { + return err + } + defer os.RemoveAll(tmpdir) + + cmd := exec.Command("git", "init", ".") + cmd.Dir = tmpdir + cmd.Stdout = os.Stderr + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return err + } + + cmd = exec.Command("git", append([]string{"fast-import", "--cat-blob-fd=0"}, inargs...)...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stderr + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return err + } + + cmd = exec.Command("git", "for-each-ref", "--format=%(refname)") + cmd.Stderr = os.Stderr + b, err := cmd.Output() + if err != nil { + return err + } + refs := strings.Split(strings.TrimSuffix(string(b), "\n"), "\n") + + cmd = exec.Command("git", append(append([]string{"fast-export"}, outargs...), refs...)...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return err + } + + return nil +} -- cgit v1.2.2