Documentation ¶
Index ¶
- Variables
- func NewAddCommitCmd() *gcli.Command
- func NewAddCommitPush() *gcli.Command
- func NewBranchCmd() *gcli.Command
- func NewCheckoutCmd() *gcli.Command
- func NewCloneCmd(cfgGetter gitx.ConfigProviderFn) *gcli.Command
- func NewGitEmojisCmd() *gcli.Command
- func NewInitFlowCmd() *gcli.Command
- func NewOpenRemoteCmd(cfgGetter gitx.ConfigProviderFn) *gcli.Command
- func NewPullRequestCmd() *gcli.Command
- func NewUpdateCmd() *gcli.Command
- func NewUpdatePushCmd() *gcli.Command
- func RedirectToGitx(ctx *gcli.HookCtx) (stop bool)
- func SubCmdNotFound(ctx *gcli.HookCtx) (stop bool)
- type AutoChDir
Constants ¶
This section is empty.
Variables ¶
View Source
var BatchCmd = &gcli.Command{ Name: "batch", Aliases: []string{"bat"}, Desc: "provide some useful dev tools commands", Subs: []*gcli.Command{ BatchRunCmd, BatchPullCmd, }, Config: func(c *gcli.Command) { }, }
BatchCmd command
View Source
var BatchPullCmd = &gcli.Command{ Name: "pull", Desc: "batch pull multi git directory by `git pull`", Aliases: []string{"pul", "pl"}, Config: func(c *gcli.Command) { c. AddArg("baseDir", "base directory for run batch pull, default is work dir"). WithValue("./") c.VarOpt(&btpOpts.dirs, "dirs", "", "limit update the given dir names") }, Func: func(c *gcli.Command, args []string) error { baseDir := c.Arg("baseDir").String() absDir, err := filepath.Abs(baseDir) if err != nil { return err } dirNames := btpOpts.dirs.Split(",") dump.P(dirNames, baseDir, absDir) return nil }, }
View Source
var BatchRunCmd = &gcli.Command{ Name: "run", Desc: "batch run git command in the given dirs", Aliases: []string{"exec"}, Config: func(c *gcli.Command) { btrOpts.BindCommonFlags(c) c.AddArg("dirs", "run command in the given dirs, if empty, run on all subdir") }, Func: func(c *gcli.Command, args []string) error { return nil }, }
View Source
var BranchCreateCmd = &gcli.Command{ Name: "new", Desc: "create and checkout new branch for development", Help: `Workflow: 1. git checkout DEFAULT_BRANCH 2. git pull -np SOURCE_REMOTE DEFAULT_BRANCH 3. git checkout -b NEW_BRANCH 4. git push -u DEFAULT_REMOTE NEW_BRANCH 5. git push SOURCE_REMOTE NEW_BRANCH Note: - if branch name is "fix_" or contains "{ymd}", will auto add current date string. eg: fix_ => fix_210101 `, Aliases: []string{"n", "create"}, Config: func(c *gcli.Command) { bcOpts.BindCommonFlags(c) c.BoolOpt2(&bcOpts.notToSrc, "not-to-src, nts", "dont push new branch to the source remote") c.AddArg("branch", "the new branch name, allow vars: {ymd}", true) }, Func: func(c *gcli.Command, args []string) error { cfg := apputil.GitCfgByCmdID(c) rp := cfg.LoadRepo(upOpts.Workdir) if err := rp.Check(); err != nil { return err } defRemote := rp.DefaultRemote srcRemote := rp.SourceRemote defBranch := rp.DefaultBranch newBranch := c.Arg("branch").String() ymdString := timex.Now().DateFormat("ymd") if newBranch == "fix_" { newBranch = "fix_" + ymdString } else if strings.Contains(newBranch, "{ymd}") { newBranch = strings.Replace(newBranch, "{ymd}", ymdString, -1) } rr := cmdutil.NewRunner(func(rr *cmdutil.Runner) { rr.DryRun = acpOpts.DryRun rr.Confirm = acpOpts.Confirm rr.OutToStd = true }) if rp.HasLocalBranch(newBranch) { c.Infof("TIP: local ") rr.GitCmd("checkout", newBranch).GitCmd("pull", "-np") return rr.Run() } colorp.Infoln("Fetch remotes and check branch exists") rr.GitCmd("fetch", "--all", "-np") if err := rr.RunReset(); err != nil { return err } rr.Reset() if rp.HasOriginBranch(newBranch) { colorp.Warnf("the branch %q already exists in remote %q\n", newBranch, defRemote) return rp.QuickRun("checkout", newBranch) } if rp.HasSourceBranch(newBranch) { colorp.Warnf("the branch %q already exists in remote %q\n", newBranch, srcRemote) rr.GitCmd("checkout", newBranch).GitCmd("push", "-u", defRemote, newBranch) return rr.Run() } colorp.Infoln("Do checkout new branch and push to remote") curBranch := rp.CurBranchName() if defBranch != curBranch { rr.GitCmd("checkout", defBranch) } rr.GitCmd("pull", srcRemote, defBranch) rr.GitCmd("checkout", "-b", newBranch) rr.GitCmd("push", "-u", defRemote, newBranch) if !bcOpts.notToSrc { rr.GitCmd("push", srcRemote, newBranch) } return rr.Run() }, }
BranchCreateCmd instance
View Source
var BranchDeleteCmd = &gcli.Command{ Name: "delete", Desc: "delete branches", Aliases: []string{"del", "rm"}, Examples: ` # Delete local branches {$fullCmd} fix_1 fix_2 fea_1 {$fullCmd} "fea*" # use glob match {$fullCmd} "prefix:fea" # use prefix match {$fullCmd} "suffix:_dev" # use suffix match {$fullCmd} "regex:fix_\d+" # use regex match # Delete remote branches {$fullCmd} -r origin fix_* # use glob match `, Config: func(c *gcli.Command) { bdOpts.BindCommonFlags(c) c.MustFromStruct(&bdOpts) c.AddArg("branches", "the branch names or match pattern(can with match mode)", true, true) }, Func: func(c *gcli.Command, args []string) error { rp := app.Gitx().LoadRepo(blOpts.Workdir) if blOpts.Fetch { if err := rp.FetchAll("-np"); err != nil { return err } } matcher := brinfo.NewMulti() patterns := c.Arg("branches").Strings() var branches []string for _, pattern := range patterns { if gitutil.IsBranchName(pattern) { branches = append(branches, pattern) continue } matcher.Add(brinfo.NewMatcher(pattern)) } bis := rp.BranchInfos() opt := &gitw.SearchOpt{Remote: bdOpts.Remote} opt.Flag = basefn.OrValue(opt.Remote == "", gitw.BrSearchLocal, gitw.BrSearchRemote) brs := bis.SearchV2(matcher, opt) num := len(brs) rp.SetDryRun(blOpts.DryRun) colorp.Cyanf("Will delete %d branches, Glob match number %d\n", num+len(branches), num) if blOpts.Confirm && !cliutil.Confirm("Do you want to continue?") { colorp.Cyanln("Canceled") return nil } for _, info := range brs { colorp.Warnf("Do delete branch: %s\n", info.Name) if err := rp.BranchDelete(info.Short, info.Remote); err != nil { return err } } return nil }, }
BranchDeleteCmd quickly delete branches
View Source
var BranchListCmd = &gcli.Command{ Name: "list", Desc: "list or search branches on local or remote", Aliases: []string{"search", "ls"}, Examples: ` # List branches by glob pattern {$fullCmd} -m "fea*" {$fullCmd} -m "glob:fix_2[1|2]*" # List branches by prefix pattern {$fullCmd} -m "prefix:fea-" # List branches by regex pattern {$fullCmd} -m "regex:fea_\d+" # match like fix_23_04 {$fullCmd} -m "regex:f[a-z]*_[0-9]+_\d+" # Find and delete remote branches {$fullCmd} -r origin -m fix_* --delete # or {$fullCmd} -r origin -m fix_* -x "git push {remote} --delete {branch}" `, Config: func(c *gcli.Command) { blOpts.BindCommonFlags(c) c.MustFromStruct(&blOpts, gflag.TagRuleNamed) c.AddArg("match", "the branch name match pattern, same as --match|-m|-p").WithAfterFn(func(arg *gcli.CliArg) error { blOpts.Match = arg.String() return nil }) }, Func: func(c *gcli.Command, args []string) error { rp := app.Gitx().LoadRepo(blOpts.Workdir) if blOpts.Fetch { if err := rp.FetchAll("-np"); err != nil { return err } } colorp.Infoln("Load repo branches ...") bis := rp.BranchInfos() if blOpts.Match == "" { tle := "Local" var brs []*gitw.BranchInfo if blOpts.All { tle = "Local+Remotes" brs = bis.All() } else if blOpts.Remote != "" { tle = blOpts.Remote brs = bis.Remotes(blOpts.Remote) } else { brs = bis.Locales() } colorp.Cyanf("Branches on %q(total: %d)\n", tle, len(brs)) for i, info := range brs { colorp.Infof(" %-24s %s\n", info.Short, info.HashMsg) if blOpts.Limit > 0 && i+1 >= blOpts.Limit { break } } return nil } tle := "Local" if blOpts.All { tle = "Local+Remotes" } else if blOpts.Remote != "" { tle = blOpts.Remote } matcher := brinfo.NewMatcher(blOpts.Match) opt := &gitw.SearchOpt{Remote: blOpts.Remote, Limit: blOpts.Limit} opt.Flag = basefn.OrValue(opt.Remote == "", gitw.BrSearchLocal, gitw.BrSearchRemote) brs := bis.SearchV2(matcher, opt) colorp.Cyanf("Branches on %q(found: %d, %s)\n", tle, len(brs), matcher.String()) if blOpts.Confirm && !cliutil.Confirm("Do you want to continue?") { colorp.Cyanln("Canceled") return nil } spl := textutil.NewVarReplacer("{,}") rp.SetDryRun(blOpts.DryRun) for _, info := range brs { if blOpts.Delete { colorp.Warnf("Do delete branch: %s\n", info.Name) if err := rp.BranchDelete(info.Short, info.Remote); err != nil { return err } } else if blOpts.Exec != "" { vs := map[string]string{ "branch": info.Short, "hash": info.Hash, "remote": info.Remote, } execCmd := cmdr.NewCmdline(spl.RenderSimple(blOpts.Exec, vs)). WithWorkDir(rp.Dir()). WithDryRun(blOpts.DryRun). PrintCmdline() if err := execCmd.Run(); err != nil { return err } } else { colorp.Infof(" %-24s %s\n", info.Short, info.HashMsg) } } if blOpts.Update { if err := rp.FetchAll("-np"); err != nil { return err } } return nil }, }
BranchListCmd instance
View Source
var BranchSetupCmd = &gcli.Command{ Name: "setup", Desc: "setup a new checkout branch on fork develop mode", Help: `Workflow: git fetch DEFAULT_REMOTE if DEFAULT_REMOTE/BRANCH exist: git branch --set-upstream-to=DEFAULT_REMOTE/BRANCH else: git push --set-upstream DEFAULT_REMOTE BRANCH git push SOURCE_REMOTE BRANCH `, Aliases: []string{"init"}, Config: func(c *gcli.Command) { bsOpts.BindCommonFlags(c) c.BoolOpt2(&bsOpts.notToSrc, "not-to-src, nts", "dont push branch to the source remote") }, Func: func(c *gcli.Command, args []string) (err error) { cfg := apputil.GitCfgByCmdID(c) rp := cfg.LoadRepo(bsOpts.Workdir) if err := rp.Check(); err != nil { return err } if err := rp.FetchOrigin(); err != nil { return err } brName := rp.CurBranchName() if rp.HasOriginBranch(brName) { err = rp.Cmd("branch").Argf("--set-upstream-to=%s/%s", rp.DefaultRemote, brName).Run() } else { err = rp.Cmd("push", "-u", rp.DefaultRemote, brName).Run() } return basefn.CallOn(!bsOpts.notToSrc, func() error { return rp.Cmd("push", rp.SourceRemote, brName).Run() }) }, }
BranchSetupCmd instance
View Source
var ( // ChangelogCmd instance ChangelogCmd = &gcli.Command{ Name: "chlog", Desc: "Generate changelog message for git repository", Aliases: []string{"cl", "clog", "changelog"}, Examples: ` {$binWithCmd} last head {$binWithCmd} last head --style gh-release --no-merges {$binWithPath} v2.0.9 v2.0.10 --no-merges --style gh-release --exclude "cs-fixer,format codes" `, Config: func(c *gcli.Command) { c.AddArg("oldVersion", `The old version. eg: v1.0.2, 349238b - keywords 'last/latest' will auto use latest tag - keywords 'prev/previous' will auto use previous tag`). WithFn(func(arg *gcli.Argument) { arg.Required = true }) c.AddArg("newVersion", `The new version. eg: v1.2.2, 66c0df1 - keywords 'head' will auto use Head commit`). WithFn(func(arg *gcli.Argument) { arg.Required = true }) c.VarOpt(&chlogOpts.limit, "limit", "", "limit update the given dir names") c.StrOpt2(&chlogOpts.dstFile, "file", "Export changelog message to the file, default dump to stdout") c.StrOpt2(&chlogOpts.repoUrl, "repo-url", ` The git repo URL address. eg: https://github.com/inhere/kite default will auto use current git origin remote url `) c.StrOpt(&chlogOpts.style, "style", "s", "default", ` The style for generate for changelog. allow: markdown(md), simple, gh-release(ghr) `) c.BoolOpt2(&chlogOpts.fetchTags, "fetch-tags", "Update repo tags list by 'git fetch --tags'") c.BoolOpt2(&chlogOpts.noMerges, "no-merges", "dont contains merge request logs") c.BoolOpt2(&chlogOpts.unShallow, "unshallow", "Convert to a complete warehouse, useful on GitHub Action.") }, Func: func(c *gcli.Command, args []string) error { absDir, err := filepath.Abs(c.WorkDir()) if err != nil { return err } repo := gitw.NewRepo(absDir) colorp.Infoln("chlog options:") dump.NoLoc(repo.DefaultRemoteInfo()) cl := chlog.New() cl.Formatter = &chlog.MarkdownFormatter{ RepoURL: "https://github.com/gookit/gitw", } cl.WithConfigFn(func(c *chlog.Config) { c.GroupPrefix = "\n### " c.GroupSuffix = "\n" }) chlogOpts.sha1 = c.Arg("oldVersion").String() chlogOpts.sha2 = c.Arg("newVersion").String() colorp.Infoln("chlog options:") dump.NoLoc(chlogOpts) cl.FetchGitLog(chlogOpts.sha1, chlogOpts.sha2, "--no-merges") if cl.LogIsEmpty() { colorp.Infoln("Not found change log in two hash version") return nil } if err = cl.Generate(); err != nil { return err } dump.P(cl.Changelog()) return nil }, } )
View Source
var GitCommands = &gcli.Command{ Name: "git", Desc: "tools for quick use `git` and more extra commands", Aliases: []string{"g", "gitx"}, Subs: []*gcli.Command{ RepoInfoCmd, RemoteInfoCmd, NewPullRequestCmd(), NewCloneCmd(configProvider), NewAddCommitPush(), NewAddCommitCmd(), NewUpdateCmd(), NewUpdatePushCmd(), NewOpenRemoteCmd(configProvider), NewInitFlowCmd(), NewCheckoutCmd(), ShowLogCmd, ChangelogCmd, TagCmd, BatchCmd, NewBranchCmd(), NewGitEmojisCmd(), }, Config: func(c *gcli.Command) { GitOpts.BindCommonFlags(c) GitOpts.BindChdirFlags(c) c.On(events.OnCmdSubNotFound, SubCmdNotFound) c.On(events.OnCmdRunBefore, func(ctx *gcli.HookCtx) bool { c.Infoln("[kite.GIT] Workdir:", c.WorkDir()) return false }) }, }
GitCommands commands for use git
View Source
var GitOpts = struct { AutoChDir cmdbiz.CommonOpts }{}
GitOpts object
View Source
var RemoteInfoCmd = &gcli.Command{ Name: "remote", Aliases: []string{"rmt"}, Desc: "git remote command", Func: func(c *gcli.Command, args []string) error { err := gitw.New("remote", "-v").Run() if err != nil { return err } return nil }, }
RemoteInfoCmd instance
View Source
var RepoInfoCmd = &gcli.Command{ Name: "info", Desc: "show some info for the git repository", Config: func(c *gcli.Command) { riOpts.BindCommonFlags(c) }, Func: func(c *gcli.Command, args []string) error { rp := gitw.NewRepo(riOpts.Workdir) show.AList("Information", rp.Info()) return nil }, }
RepoInfoCmd instance
View Source
var ( ShowLogCmd = &gcli.Command{ Name: "log", Desc: "display recently git commits information by `git log`", Config: func(c *gcli.Command) { c.UseSimpleRule() goutil.PanicErr(c.FromStruct(&logOpts)) c.StrOpt(&logOpts.Format, "format", "", "", "The git log option '--pretty' value.\n"+ "can be one of oneline, short, medium, full, fuller, reference, email, raw, format:string and tformat:string.", ) c.AddArg("maxCommit", "Max display how many commits") }, Func: func(c *gcli.Command, args []string) error { maxNum := c.Arg("maxCommit").Int() if maxNum < 1 { maxNum = logOpts.MaxCommit } gitLog := gitw.New("log", "--graph") gitLog.OnBeforeExec(gitw.PrintCmdline) gitLog.Argf("-%d", maxNum) gitLog.ArgIf("--color", !logOpts.NoColor) gitLog.ArgIf("--no-merges", logOpts.NoMerges) gitLog.ArgIf("--abbrev-commit", logOpts.Abbrev) gitLog.Add(`--pretty=format:%Cred%h%Creset:%C(ul yellow)%d%Creset %s (%Cgreen%cr%Creset, %C(bold blue)%an%Creset)`) return gitLog.Run() }, } )
View Source
var TagCmd = &gcli.Command{ Name: "tag", Desc: "extra git tag commands", Subs: []*gcli.Command{ TagListCmd, TagCreateCmd, TagDeleteCmd, }, }
TagCmd instance
View Source
var TagCreateCmd = &gcli.Command{ Name: "create", Aliases: []string{"new"}, Desc: "create new tag by `git tag`", Help: ` # Examples: {$fullCmd} --next {$fullCmd} -v v2.0.1 `, Config: func(c *gcli.Command) { c.MustFromStruct(&tcOpts, gflag.TagRuleSimple) }, Func: func(c *gcli.Command, args []string) error { lp := gitw.NewRepo(GitOpts.Workdir). PrintCmdOnExec(). SetDryRun(GitOpts.DryRun) err := lp.Cmd("pull", "-np").Run() if err != nil { return err } err = lp.Cmd("fetch", "--tags").Run() if err != nil { return err } lastVer := lp.LargestTag() nextVer := tcOpts.Version if len(nextVer) == 0 { nextVer = gitutil.NextVersion(lastVer) } else { var ok bool nextVer, ok = gitutil.FormatVersion(nextVer) if !ok { return c.NewErrf("invalid version: %s", nextVer) } } nextVer = "v" + nextVer message := tcOpts.Message if len(message) == 0 { message = ":bookmark: release the " + nextVer } show.AList("create tag", map[string]any{ "Hash ID": tcOpts.Hash, "Prev tag": lastVer, "New tag": nextVer, "Tag Message": message, "Dry Run": GitOpts.DryRun, }) if interact.Unconfirmed("Ensure create and push new tag?", true) { colorp.Infoln("Quit, Bye!") return nil } err = lp.Cmd("tag", "-a", nextVer, "-m", message).Run() if err != nil { return err } err = lp.Cmd("push", "origin", nextVer).Run() if err != nil { return err } colorp.Successf("Successful create tag: %s\n", nextVer) return nil }, }
TagCreateCmd instance
View Source
var TagDeleteCmd = &gcli.Command{ Name: "delete", Aliases: []string{"del", "rm", "remove"}, Desc: "delete exists tags by `git tag`", Func: func(c *gcli.Command, args []string) error { return errors.New("TODO") }, }
TagDeleteCmd instance
View Source
var TagListCmd = &gcli.Command{ Name: "list", Aliases: []string{"ls"}, Desc: "list tags for the git repository", Func: func(c *gcli.Command, args []string) error { return errors.New("TODO") }, }
TagListCmd instance
Functions ¶
func NewCloneCmd ¶
func NewCloneCmd(cfgGetter gitx.ConfigProviderFn) *gcli.Command
NewCloneCmd instance
func NewOpenRemoteCmd ¶
func NewOpenRemoteCmd(cfgGetter gitx.ConfigProviderFn) *gcli.Command
NewOpenRemoteCmd instance
Types ¶
Source Files ¶
Click to show internal directories.
Click to hide internal directories.