func (cb *Defn) applyVarsToField(desc, fieldName, fieldValue string) (string, error) { t := template.New(fieldName) t, err := t.Parse(fieldValue) if err != nil { return "", out.WrapErrf(err, 3004, "Parsing problem applying templates to:\n%v\n URI Template: %v", desc, fieldValue) } buf := new(bytes.Buffer) err = t.Execute(buf, cb.Vars) if err != nil { return "", out.WrapErrf(err, 3005, "Template execute problem with codebase repo definition\n%v\n URI Template: %v", desc, fieldValue) } result := fmt.Sprintf("%s", buf) return result, nil }
// Read will, given an io.Reader, attempt to scan in the codebase contents // and "fill out" the given Defn structure for you. What could // go wrong? If anything a non-nil error is returned. func (cb *Defn) Read(r io.Reader) error { codebaseMap := make(map[string]interface{}) decJSON := json.NewDecoder(r) err := decJSON.Decode(&codebaseMap) if err != nil { if serr, ok := err.(*json.SyntaxError); ok { return out.WrapErrf(err, 3001, "Failed to decode codebase JSON (Bad Char Offset: %v)", serr.Offset) } return out.WrapErr(err, "Failed to decode codebase JSON file", 3001) } config := &mapstructure.DecoderConfig{ WeaklyTypedInput: true, Result: cb, } decoder, err := mapstructure.NewDecoder(config) if err != nil { return out.WrapErr(err, "Failed to prepare codebase file decoder", 3002) } err = decoder.Decode(codebaseMap) if err != nil { return out.WrapErr(err, "Failed to decode codebase file contents", 3003) } // codebase definitions can be reduced in size if the person defining that // file uses variables to identify common repo references and such, lets // examine those vars and, if any, make sure we "expand" them so the codebase // definition is complete. Write() will "smart" subtitute the vars back. if err = cb.expandVarUse(); err != nil { return err } return nil }
// findGitDirs expects to be pointed at a git workspace, either // bare or standard. It'll find the gitdir and worktree dirs // and return them, if it fails it'll return non-nil err. Params: // path (string): path to the git workspace // Returns: // gitDir (string): path to git metadata location // workTreeDir (string): working tree, "" if bare clone // err (error): a valid error if unable to find a git repo func findGitDirs(path string) (string, string, error) { gitDir := filepath.Join(path, ".git") // see if std git clone var err error var exists bool if exists, err = dir.Exists(gitDir); exists && err == nil { return gitDir, path, nil } gitRefsDir := filepath.Join(path, "refs") if exists, err = dir.Exists(gitRefsDir); exists && err == nil { gitConfigFile := filepath.Join(path, "config") if exists, err = file.Exists(gitConfigFile); exists && err == nil { return path, "", nil } } if err == nil { return "", "", out.WrapErrf(ErrNoExist, 4500, "Unable to find valid git clone under path: %s", path) } return "", "", out.WrapErrf(ErrNoExist, 4500, "Unable to find valid git clone under path: %s\n existence err: %s", path, err) }
// BzrExists verifies the local repo or remote location is of the Bzr repo type, // returns where it was found ("" if not found) and any error. If it does not // exist a wrapped ErrNoExist error is returned (use out.IsError() to check) func BzrExists(e Existence, l Location) (string, Resulter, error) { results := newResults() var err error path := "" if l == LocalPath { if exists, err := dir.Exists(e.LocalRepoPath() + "/.bzr"); exists && err == nil { return e.LocalRepoPath(), nil, nil } err = out.WrapErrf(ErrNoExist, 4505, "Local bzr location, \"%s\", does not exist, err: %s", e.LocalRepoPath(), err) } else { // checking remote "URL" as well as possible for current VCS.. remote := e.Remote() scheme := url.GetScheme(remote) // if we have a scheme then just see if the repo exists... if scheme != "" { var result *Result result, err = run(bzrTool, "info", remote) results.add(result) if err == nil { path = remote } } else { vcsSchemes := e.Schemes() for _, scheme = range vcsSchemes { var result *Result result, err = run(bzrTool, "info", scheme+"://"+remote) results.add(result) if err == nil { path = scheme + "://" + remote break } } } if err == nil { return path, results, nil } err = out.WrapErrf(ErrNoExist, 4506, "Remote bzr location, \"%s\", does not exist, err: %s", e.Remote(), err) } return path, results, err }
// GitHookInstall is used to install a hook into a git clone, params: // h (*GitHookMgr): the hook mgr structure (find location of repo/etc) // path (string): where is the hook we wish to install? // name (string): what is the "git name" for the hook? // link (bool): is hook a symlink to hookPath, or full copy/install? // Returns full path/name to git hook installed along w/any error seen func GitHookInstall(h *GitHookMgr, path, name string, link bool) (string, error) { repoPath, _, err := h.Exists(LocalPath) hookInstallPath := "" if err == nil && repoPath != "" { // if the local path exists... hookInstallPath = filepath.Join(repoPath, ".git", "hooks", name) if isBareRepo(repoPath) { hookInstallPath = filepath.Join(repoPath, "hooks", name) } if there, err := file.Exists(hookInstallPath); err == nil && there { err = os.Remove(hookInstallPath) if err != nil { return "", out.WrapErr(err, "Failed to remove previously installed hook", 4510) } } if there, err := file.Exists(path); err != nil || !there { if err != nil { return "", out.WrapErr(err, "Hook install failed checking source hook existence", 4511) } return "", out.NewErrf(4512, "Hook install failed, hook source path does not exist:\n path: %s", path) } oldUmask := syscall.Umask(0) defer syscall.Umask(oldUmask) if link { // if symlink desired, try and create that err = os.Symlink(path, hookInstallPath) if err != nil { err = out.WrapErrf(err, 4513, "Hook install failed, failed to set up symlink:\n linktgt: %s\n link: %s\n", path, hookInstallPath) } } else { // otherwise try and copy in the hook file _, err = file.CopyFileSetPerms(path, hookInstallPath, 0775) if err != nil { err = out.WrapErrf(err, 4514, "Hook install failed, failed to copy hook file:\n hook source path %s\n hook install path: %s\n", path, hookInstallPath) } } } return hookInstallPath, err }
// GitExists verifies the local repo or remote location is a Git repo, // returns where it was found (or "" if not found), the results // of any git cmds run (cmds and related output) and any error. // Note that if no git cmds run then Resulter won't have any data // (which occurs if the git repo is local). If the git repo does not // exist a wrapped ErrNoExist is returned (use out.IsError() to check) func GitExists(e Existence, l Location) (string, Resulter, error) { results := newResults() var err error path := "" if l == LocalPath { _, _, err = findGitDirs(e.LocalRepoPath()) // clone? wrapped ErrNoExists if not if err == nil { return e.LocalRepoPath(), nil, nil // it's a local git clone, success } } else { // checking remote "URL" as well as possible for current VCS.. remote := e.Remote() scheme := url.GetScheme(remote) if scheme != "" { // if we have a scheme then see if the repo exists... var result *Result result, err = run(gitTool, "ls-remote", remote) results.add(result) if err == nil { path = remote } } else { vcsSchemes := e.Schemes() for _, scheme = range vcsSchemes { var result *Result result, err = run(gitTool, "ls-remote", scheme+"://"+remote) results.add(result) if err == nil { path = scheme + "://" + remote break } } } if err == nil { return path, results, nil } err = out.WrapErrf(ErrNoExist, 4501, "Remote git location does not exist: %s\n run err: %s", e.Remote(), err) } return path, results, err }