mirror of
https://github.com/splitsh/lite.git
synced 2024-05-02 06:32:53 +02:00
Add excluding directories support
This commit is contained in:
parent
eaede0baa4
commit
5dbf39b5b4
16
README.md
16
README.md
|
@ -128,10 +128,18 @@ splitsh-lite --prefix=lib/ --origin=origin/1.0 --path=/path/to/repo
|
|||
|
||||
Available options:
|
||||
|
||||
* `--prefix` is the prefix of the directory to split; you can put the split
|
||||
contents in a sub-directory of the target repository by using the
|
||||
`--prefix=from:to` syntax; split several directories by passing multiple
|
||||
`--prefix` flags;
|
||||
* `--prefix` is the prefix of the directory to split; the value can be one of
|
||||
the following:
|
||||
|
||||
* `from`: the origin directory to split;
|
||||
|
||||
* `from:to`: move the split content to a sub-directory on the target;
|
||||
|
||||
* `from:to:exclude`: exclude a directory from the origin `from` directory
|
||||
(use `from:to:exclude1:exclude2:...` to exclude more than one
|
||||
directory).
|
||||
|
||||
Split several directories by passing multiple `--prefix` flags;
|
||||
|
||||
* `--path` is the path of the repository to split (current directory by default);
|
||||
|
||||
|
|
10
main.go
10
main.go
|
@ -24,8 +24,14 @@ func (p *prefixesFlag) Set(value string) error {
|
|||
parts := strings.Split(value, ":")
|
||||
from := parts[0]
|
||||
to := ""
|
||||
if len(parts) > 1 {
|
||||
excludes := make([]string, 0)
|
||||
if len(parts) >= 2 {
|
||||
to = parts[1]
|
||||
if len(parts) > 2 {
|
||||
for _, exclude := range parts[2:] {
|
||||
excludes = append(excludes, exclude)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// value must be unique
|
||||
|
@ -36,7 +42,7 @@ func (p *prefixesFlag) Set(value string) error {
|
|||
}
|
||||
}
|
||||
|
||||
*p = append(*p, &splitter.Prefix{From: from, To: to})
|
||||
*p = append(*p, &splitter.Prefix{From: from, To: to, Excludes: excludes})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,9 @@ func key(config *Config) []byte {
|
|||
for _, prefix := range config.Prefixes {
|
||||
io.WriteString(h, prefix.From)
|
||||
io.WriteString(h, prefix.To)
|
||||
for _, exclude := range prefix.Excludes {
|
||||
io.WriteString(h, exclude)
|
||||
}
|
||||
}
|
||||
|
||||
return h.Sum(nil)
|
||||
|
|
|
@ -11,8 +11,9 @@ import (
|
|||
|
||||
// Prefix represents which paths to split
|
||||
type Prefix struct {
|
||||
From string
|
||||
To string
|
||||
From string
|
||||
To string
|
||||
Excludes []string
|
||||
}
|
||||
|
||||
// Config represents a split configuration
|
||||
|
|
|
@ -61,13 +61,17 @@ func newState(config *Config, result *Result) (*state, error) {
|
|||
}
|
||||
|
||||
if config.Debug {
|
||||
state.logger.Printf("Splitting %s\n", state.originBranch)
|
||||
state.logger.Printf("Splitting %s", state.originBranch)
|
||||
for _, v := range config.Prefixes {
|
||||
to := v.To
|
||||
if to == "" {
|
||||
to = "ROOT"
|
||||
}
|
||||
state.logger.Printf(" From \"%s\" to \"%s\"\n", v.From, to)
|
||||
state.logger.Printf(` From "%s" to "%s"`, v.From, to)
|
||||
if (len(v.Excludes)) == 0 {
|
||||
} else {
|
||||
state.logger.Printf(` Excluding "%s"`, strings.Join(v.Excludes, `", "`))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +83,7 @@ func newState(config *Config, result *Result) (*state, error) {
|
|||
|
||||
// simplePrefix contains the prefix when there is only one
|
||||
// with an empty value (target)
|
||||
if len(config.Prefixes) == 1 && config.Prefixes[0].To == "" {
|
||||
if len(config.Prefixes) == 1 && config.Prefixes[0].To == "" && len(config.Prefixes[0].Excludes) == 0 {
|
||||
state.simplePrefix = config.Prefixes[0].From
|
||||
}
|
||||
|
||||
|
@ -284,6 +288,14 @@ func (s *state) treeByPaths(tree *git.Tree) (*git.Tree, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if len(prefix.Excludes) > 0 {
|
||||
prunedTree, err := s.pruneTree(splitTree, prefix.Excludes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
splitTree = prunedTree
|
||||
}
|
||||
|
||||
// adding the prefix
|
||||
if prefix.To != "" {
|
||||
prefixedTree, err = s.addPrefixToTree(splitTree, prefix.To)
|
||||
|
@ -360,6 +372,53 @@ func (s *state) addPrefixToTree(tree *git.Tree, prefix string) (*git.Tree, error
|
|||
return prefixedTree, nil
|
||||
}
|
||||
|
||||
func (s *state) pruneTree(tree *git.Tree, excludes []string) (*git.Tree, error) {
|
||||
var err error
|
||||
treeBuilder, err := s.repo.TreeBuilder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer treeBuilder.Free()
|
||||
|
||||
err = tree.Walk(func(path string, entry *git.TreeEntry) error {
|
||||
// always add files at the root directory
|
||||
if entry.Type == git.ObjectBlob {
|
||||
if err := treeBuilder.Insert(entry.Name, entry.Id, git.FilemodeBlob); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if entry.Type != git.ObjectTree {
|
||||
// should never happen
|
||||
return fmt.Errorf("Unexpected entry %s/%s (type %s)", path, entry.Name, entry.Type)
|
||||
}
|
||||
|
||||
// exclude directory in excludes
|
||||
for _, exclude := range excludes {
|
||||
if entry.Name == exclude {
|
||||
return git.TreeWalkSkip
|
||||
}
|
||||
}
|
||||
|
||||
if err := treeBuilder.Insert(entry.Name, entry.Id, git.FilemodeTree); err != nil {
|
||||
return err
|
||||
}
|
||||
return git.TreeWalkSkip
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
treeOid, err := treeBuilder.Write()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.repo.LookupTree(treeOid)
|
||||
}
|
||||
|
||||
func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oid) (*git.Oid, bool, error) {
|
||||
var identical, nonIdentical *git.Oid
|
||||
var gotParents []*git.Oid
|
||||
|
|
Loading…
Reference in a new issue