Skip to content

Commit

Permalink
push: Resolve from commit
Browse files Browse the repository at this point in the history
  • Loading branch information
niboshi committed Dec 9, 2020
1 parent 9c3a136 commit bcd527f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
33 changes: 32 additions & 1 deletion cmd/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"os"

"github.com/pfnet-research/git-ghost/pkg/ghost"
"github.com/pfnet-research/git-ghost/pkg/ghost/git"
"github.com/pfnet-research/git-ghost/pkg/ghost/types"
"github.com/pfnet-research/git-ghost/pkg/util/errors"

Expand All @@ -43,7 +44,7 @@ func NewPushCommand() *cobra.Command {
Short: "push commits(hash1...hash2), diff(hash...current state) to your ghost repo",
Long: "push commits or diff or all to your ghost repo. If you didn't specify any subcommand, this commands works as an alias for 'push diff' command.",
Args: cobra.RangeArgs(0, 1),
Run: runPushDiffCommand(&flags),
Run: runPushCommitsCommand(&flags),
}
command.AddCommand(&cobra.Command{
Use: "commits [from-hash] [to-hash(default=HEAD)]",
Expand Down Expand Up @@ -73,6 +74,26 @@ func NewPushCommand() *cobra.Command {
return command
}

func getFirstRemoteAncestorCommit(commit string) (string, errors.GitGhostError) {
dir := globalOpts.srcDir
for {
branchNames, err := git.GetRemoteBranchesContainingCommit(dir, commit)
if err != nil {
return "", err
}
if len(branchNames) > 0 {
// This commit is the first ancestor commit in any of remotes.
break
}
parentCommit, err := git.GetParentCommit(dir, commit)
if err != nil {
return "", err
}
commit = parentCommit
}
return commit, nil
}

type pushCommitsArg struct {
commitsFrom string
commitsTo string
Expand Down Expand Up @@ -111,6 +132,16 @@ func (arg pushCommitsArg) validate() errors.GitGhostError {
func runPushCommitsCommand(flags *pushFlags) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
pushArg := newPushCommitsArg(args)

// If commitsFrom is not given, find the first ancestor commit that is included in any of remotes.
if pushArg.commitsFrom == "" {
commitsFrom, err := getFirstRemoteAncestorCommit(pushArg.commitsTo)
if err != nil {
errors.LogErrorWithStack(err)
os.Exit(1)
}
pushArg.commitsFrom = commitsFrom
}
if err := pushArg.validate(); err != nil {
errors.LogErrorWithStack(err)
os.Exit(1)
Expand Down
26 changes: 26 additions & 0 deletions pkg/ghost/git/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package git

import (
"bytes"
"fmt"
"os/exec"
"strings"
Expand Down Expand Up @@ -146,3 +147,28 @@ func ResetHardToBranch(dir, branch string) errors.GitGhostError {
exec.Command("git", "-C", dir, "reset", "--hard", branch),
)
}

// GetParentCommit returns the parent commit of the given commit
func GetParentCommit(dir, commit string) (string, errors.GitGhostError) {
resultBytes, err := util.JustOutputCmd(exec.Command("git", "-C", dir, "rev-parse", fmt.Sprintf("%s^", commit)))
if err != nil {
return "", errors.WithStack(gherrors.WithMessage(err, "failed to get the parent commit of a commit"))
}
return strings.TrimSuffix(string(resultBytes), "\n"), nil
}

// GetRemoteBranchesContainingCommit returns a slice of remote branch names each of which contain the given commit
func GetRemoteBranchesContainingCommit(dir, commit string) ([]string, errors.GitGhostError) {
resultBytes, err := util.JustOutputCmd(exec.Command("git", "-C", dir, "branch", "--no-color", "--format", "%(refname)", "--remotes", "--contains", commit))
if err != nil {
return nil, errors.WithStack(gherrors.WithMessage(err, "failed to get remote branches containing a commit"))
}
var branchNames []string
for _, line := range bytes.Split(resultBytes, []byte("\n")) {
branchName := string(line)
if len(branchName) > 0 {
branchNames = append(branchNames, branchName)
}
}
return branchNames, nil
}

0 comments on commit bcd527f

Please sign in to comment.