package gitpb import ( "errors" "fmt" "os/user" "path/filepath" "go.wit.com/log" ) func (repo *Repo) CheckoutMasterError() error { bName := repo.GetMasterBranchName() if err := repo.checkoutBranchError(bName); err != nil { return err } return nil } // if you manage to leave yourself on a branch // that has been deleted, git porcelain will report // the repo as having changes (aka 'dirty') // then this code won't let you switch branches // this bypasses those checks and moves you // to a working branch. 1st 'devel', then 'master' func (r *Repo) CheckoutForce() error { brName := r.GetDevelBranchName() if r.IsLocalBranch(brName) { log.Info(r.FullPath, "Checking out local devel") if err := r.checkoutBranchForceUnsafe(brName); err == nil { return nil } } if r.IsRemoteBranch(brName) { log.Info(r.FullPath, "There is a remote devel branch") // ya, it could run this twice. whatever if err := r.checkoutBranchForceUnsafe(brName); err == nil { return nil } } else { log.Info(r.FullPath, "There is not a remote devel branch", brName) } brName = r.GetMasterBranchName() if r.IsLocalBranch(brName) { log.Info(r.FullPath, "Checking out local master") if err := r.checkoutBranchForceUnsafe(brName); err == nil { return nil } } if r.IsRemoteBranch(brName) { log.Info(r.FullPath, "Checking out remote master") // things are jacked if err := r.checkoutBranchForceUnsafe(brName); err == nil { return nil } else { return err } } else { log.Info(r.FullPath, "There is not a remote master branch", brName) } log.Info(r.FullPath, "forge doesn't know how to handle this yet") return errors.New("no working devel or master branches todo: find one here") } // deprecate this func (repo *Repo) CheckoutMaster() bool { bName := repo.GetMasterBranchName() if repo.checkoutBranch(bName) { return true } return false } func (repo *Repo) CheckoutDevelError() error { bName := repo.GetDevelBranchName() if err := repo.checkoutBranchError(bName); err != nil { return err // switch ok } repo.DevelBranchName = bName return nil } // deprecate this func (repo *Repo) CheckoutDevel() bool { bName := repo.GetDevelBranchName() if repo.checkoutBranch(bName) { repo.DevelBranchName = bName return true // switch ok } return false } func (repo *Repo) CheckoutUser() error { bName := repo.GetUserBranchName() if bName == "" { usr, _ := user.Current() repo.SetUserBranchName(usr.Username) bName = usr.Username log.Info("gitpb CheckoutUser() user branchname was blank") } return repo.createUserBranch(bName) /* if err != nil { log.Info("attempting checkout user error", repo.GetGoPath(), bName, err) } return err */ } func (repo *Repo) BranchExists(bName string) bool { // fixme after move to protobuf return true } func (repo *Repo) checkoutBranchError(bName string) error { if !repo.BranchExists(bName) { return fmt.Errorf("no branch") } if bName == "" { return fmt.Errorf("branch name was blank") } if repo.CheckDirty() { log.Log(INFO, repo.GetFullPath(), "is dirty") return fmt.Errorf("repo is dirty") } cmd := []string{"git", "checkout", bName} r := repo.Run(cmd) if r.Error != nil { log.Log(INFO, "git checkout error:", r.Error) return r.Error } // remove this if everything works realname := repo.GetCurrentBranchName() realversion := repo.GetCurrentBranchVersion() log.Info("checkoutranchError()", repo.GetFullPath(), "realname =", realname, "realversion =", realversion) /* this is deprecated now probably if realname != bName { log.Log(INFO, "git checkout failed", repo.GetFullPath(), bName, "!=", realname) return fmt.Errorf("repo Reload() name match failure") } */ return nil } // force checkout. will delete everyhing. this is bad // only do this when you have lost all hope func (repo *Repo) checkoutBranchForceUnsafe(brName string) error { cmd := []string{"git", "checkout", brName, "--force"} var err error err = repo.RunVerbose(cmd) if err != nil { log.Info(repo.FullPath, "git checkout error", err) return err } // if r.Error != nil { // if r.Exit != 0 { // log.Info(repo.Fullpath, "git checkout exit not zero", r.Exit) // return errors.New("git checkout returned -1") //} // if r.Error != nil { // log.Info(repo.FullPath, "git checkout error:", r.Error) // return r.Error // } log.Info(repo.FullPath, "git checkout should have worked") return nil } func (repo *Repo) checkoutBranch(bName string) bool { if !repo.BranchExists(bName) { return false } if bName == "" { return false } if repo.CheckDirty() { log.Log(INFO, repo.GetFullPath(), "is dirty") return false } cmd := []string{"git", "checkout", bName} r := repo.Run(cmd) if r.Error != nil { log.Log(INFO, "git checkout error:", r.Error) } realname := repo.GetCurrentBranchName() realversion := repo.GetCurrentBranchVersion() log.Log(INFO, repo.GetFullPath(), "realname =", realname, "realversion =", realversion) if realname != bName { log.Log(INFO, "git checkout failed", repo.GetFullPath(), bName, "!=", realname) return false } return true } // actually creates a local user branch func (repo *Repo) createUserBranch(branch string) error { if branch == "" { // get the username here? usr, err := user.Current() if err != nil { return err } branch = usr.Username } if repo.IsDirty() { // never change repos on dirty branches return fmt.Errorf("repo is dirty") } if repo.Exists(filepath.Join(".git/refs/heads", branch)) { var err error // there is already a local user branch cmd := []string{"git", "checkout", branch} if _, err = repo.RunVerboseOnError(cmd); err == nil { return nil } log.Log(INFO, "git checkout error:", err) } if repo.Exists(filepath.Join(".git/refs/remote/origin", branch)) { var err error // there is a remote user branch // todo: check other remotes cmd := []string{"git", "checkout", branch} if _, err = repo.RunVerboseOnError(cmd); err == nil { return nil } log.Log(INFO, "git checkout error:", err) } if repo.GetCurrentBranchName() != repo.GetDevelBranchName() { repo.CheckoutDevel() } repo.ReloadCheck() if repo.GetCurrentBranchName() != repo.GetDevelBranchName() { log.Info("create user branch will probably fail", repo.GetGoPath()) // TODO: FIX THIS // return fmt.Errorf("repo must be on devel branch %s", repo.GetGoPath()) } // create the branch from devel cmd := []string{"git", "branch", branch} if _, err := repo.RunVerboseOnError(cmd); err != nil { return err } cmd = []string{"git", "checkout", branch} if _, err := repo.RunVerboseOnError(cmd); err != nil { return err } return nil }