diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2017-11-23 03:10:14 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2017-11-23 03:10:14 -0500 |
commit | 81ce784f367dcd29de79cb12a750b28a7facfaac (patch) | |
tree | c9ad3772f70ac28948a1060fcbde923e10e181c3 | |
parent | 991fcf53af926668c513b8fd74d47fcf8f243756 (diff) |
more
-rw-r--r-- | filter.go | 83 | ||||
-rw-r--r-- | git.go | 29 | ||||
-rw-r--r-- | heuristics.go | 51 |
3 files changed, 126 insertions, 37 deletions
@@ -13,6 +13,11 @@ import ( "git.lukeshu.com/go/libfastimport" ) +type fullcommit struct { + metadata libfastimport.CmdCommit + fileactions []libfastimport.Cmd +} + type Filter struct { fromRef string toPfx string @@ -20,16 +25,25 @@ type Filter struct { frontend *libfastimport.Frontend backend *libfastimport.Backend + refs map[string]string mark int + + curCommitIn libfastimport.CmdCommit + curCommitOut map[string]fullcommit } -func NewFilter(fromRef string, toPfix string) (*Filter, error) { +func NewFilter(fromRef string, toPfx string) (*Filter, error) { var err error ret := &Filter{ - fromPfx: fromPfx, + fromRef: fromRef, toPfx: toPfx, } + ret.refs, err = gitRefs() + if err != nil { + return nil, err + } + ret.frontend, err = gitFastExport( "--use-done-feature", "--no-data", @@ -144,52 +158,47 @@ func (f *Filter) Run() error { return fmt.Errorf("git fast-export kept going after 'done': cmd=%v err=%v", cmd, err) } return nil + case libfastimport.CmdReset: + // TODO case libfastimport.CmdCommit: - err = f.handleCommit(cmdt) - if err != nil { - return err - } - default: - return fmt.Errorf("Unexpected command: %[1]T(%#[1]v)", cmd) - } - } -} - -func (f *Filter) handleCommit(commit libfastimport.CmdCommit) error { - out := make(map[string]libfastimport.CmdCommit) - for _, action := range commit.Tree { - switch actiont := action.(type) { + // TODO + case libfastimport.CmdCommitEnd: + // TODO case libfastimport.FileModify: - branch_ref := f.toPfx + "/" + path.Dir(string(actiont.Path)) - from_dataref, err := f.ref2dataref(branch_ref) - if err == nil { - file_mode, file_dataref, _, err := f.backend.Ls(libfastimport.CmdLs{DataRef: from_dataref, Path: actiont.Path}) + branchname := filename2branchname(string(cmdt.Path)) + if branchname == "" { + continue + } + branch_ref := f.toPfx + "/" + path.Dir(string(cmdt.Path)) + from_dataref, from_dataref_ok := f.refs[branch_ref] + if from_dataref_ok { + file_mode, file_dataref, _, err := f.backend.Ls(libfastimport.CmdLs{DataRef: from_dataref, Path: cmdt.Path}) if err != nil { return err } - if file_mode == actiont.Mode && file_dataref == actiont.DataRef { + if file_mode == cmdt.Mode && file_dataref == cmdt.DataRef { continue } + } else { + from_dataref = branch_ref + "^0" } - if _, ok := out[branch_ref]; !ok { - out[branch_ref] = libfastimport.CmdCommit{ - Ref: branch_ref, - Mark: f.newmark(), - Author: commit.Author, - Committer: commit.Committer, - Msg: commit.Msg, - From: from_dataref - Merge: nil - Tree: nil - } + if _, ok := f.curCommitOut[branch_ref]; !ok { + f.curCommitOut[branch_ref] = fullcommit{metadata: libfastimport.CmdCommit{ + Ref: branch_ref, + Mark: f.newmark(), + Author: f.curCommitIn.Author, + Committer: f.curCommitIn.Committer, + Msg: f.curCommitIn.Msg, + From: from_dataref, + Merge: nil, + }} } - outcommit := out[branch_ref] - + //outcommit := f.curCommitOut[branch_ref] + // TODO case libfastimport.FileDelete: - ref := f.toPfx + "/" + path.Dir(string(actiont.Path)) - default: - return fmt.Errorf("Unexpected file action: %[1]T(%#[1]v)", action) + //ref := f.toPfx + "/" + path.Dir(string(cmdt.Path)) + // TODO } } return nil @@ -2,8 +2,10 @@ package svn2git2aur import ( "bytes" + "fmt" "os" "os/exec" + "strings" "git.lukeshu.com/go/libfastimport" ) @@ -77,3 +79,30 @@ func gitFastImport(args ...string) (*libfastimport.Backend, error) { return backend, nil } + +func gitRefs() (map[string]string, error) { + cmd := exec.Command("git", "for-each-ref") + b, err := cmd.Output() + if err != nil { + return nil, err + } + lines := strings.Split(string(b), "\n") + ret := make(map[string]string, len(lines)-1) + for _, line := range lines { + if line == "" { + continue + } + fields := strings.SplitN(line, " ", 3) + if len(fields) != 3 { + return nil, fmt.Errorf("malformed git for-each-ref line: %q", line) + } + refTarget := fields[0] + refType := fields[1] + refName := fields[2] + if refType != "commit" { + continue + } + ret[refName] = refTarget + } + return ret, nil +} diff --git a/heuristics.go b/heuristics.go new file mode 100644 index 0000000..1ae4395 --- /dev/null +++ b/heuristics.go @@ -0,0 +1,51 @@ +package svn2git2aur + +import ( + "path" +) + +func filename2branchname(filename string) string { + // Let us write the .SRCINFO files. + switch path.Base(filename) { + case ".AURINFO", ".SRCINFO": + return "" + } + + // There is nothing logical or universally true about the + // remainder of this function. It is simply a set of + // heuristics that works on the packages.git and community.git + // svn2git repos. + // + // The more truthful method would be to use PKGBUILD as a + // signal that a directory is a branch. However, that would + // be fairly expensive. + + branchname := path.Dir(filename) + + if branchname == "xalan-c/repos/extra-i686" { + // xalan-c has only ever been in community, not extra. + // Arch has now dropped i686, so this won't happen in + // the future either. + return "" + } + // This blackliast assumes that no package named one of those + // strings will ever exist. + for { + switch path.Base(branchname) { + case "log", "src": // packages.git + branchname = path.Dir(branchname) + case "CVS", "examples": // community.git + branchname = path.Dir(branchname) + case "repos": + return "" + default: + break + } + } + // A branch must contain a "/" + if path.Dir(branchname) == "." { + return "" + } + + return branchname +} |