package _select import ( "fmt" "io" "io/ioutil" "os" "path" "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" "github.com/MichaelMure/git-bug/repository" "github.com/MichaelMure/git-bug/util/git" "github.com/pkg/errors" ) const selectFile = "select" var ErrNoValidId = errors.New("you must provide a bug id") // ResolveBug first try to resolve a bug using the first argument of the command // line. If it fails, it fallback to the select mechanism. // // Returns: // - the bug if any // - the new list of command line arguments with the bug prefix removed if it // has been used // - an error if the process failed func ResolveBug(repo *cache.RepoCache, args []string) (*cache.BugCache, []string, error) { // At first, try to use the first argument as a bug prefix if len(args) > 0 { b, err := repo.ResolveBugPrefix(args[0]) if err == nil { return b, args[1:], nil } if err != bug.ErrBugNotExist { return nil, nil, err } } // first arg is not a valid bug prefix, we can safely use the preselected bug if any b, err := selected(repo) // selected bug is invalid if err == bug.ErrBugNotExist { // we clear the selected bug err = Clear(repo) if err != nil { return nil, nil, err } return nil, nil, ErrNoValidId } // another error when reading the bug if err != nil { return nil, nil, err } // bug is successfully retrieved if b != nil { return b, args, nil } // no selected bug and no valid first argument return nil, nil, ErrNoValidId } // Select will select a bug for future use func Select(repo *cache.RepoCache, id string) error { selectPath := selectFilePath(repo) f, err := os.OpenFile(selectPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return err } _, err = f.WriteString(id) if err != nil { return err } return f.Close() } // Clear will clear the selected bug, if any func Clear(repo *cache.RepoCache) error { selectPath := selectFilePath(repo) return os.Remove(selectPath) } func selected(repo *cache.RepoCache) (*cache.BugCache, error) { selectPath := selectFilePath(repo) f, err := os.Open(selectPath) if err != nil { if os.IsNotExist(err) { return nil, nil } else { return nil, err } } buf, err := ioutil.ReadAll(io.LimitReader(f, 100)) if err != nil { return nil, err } if len(buf) == 100 { return nil, fmt.Errorf("the select file should be < 100 bytes") } h := git.Hash(buf) if !h.IsValid() { err = os.Remove(selectPath) if err != nil { return nil, errors.Wrap(err, "error while removing invalid select file") } return nil, fmt.Errorf("select file in invalid, removing it") } b, err := repo.ResolveBug(string(h)) if err != nil { return nil, err } err = f.Close() if err != nil { return nil, err } return b, nil } func selectFilePath(repo repository.RepoCommon) string { return path.Join(repo.GetPath(), ".git", "git-bug", selectFile) }