func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. stdout, stderr, err := com.ExecCmd("git", "config", "--get", "user.name") if strings.Contains(stderr, "fatal:") { log.Fatal("repo.NewRepoContext(fail to get git user.name): %s", stderr) } else if err != nil || len(strings.TrimSpace(stdout)) == 0 { if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.email", "*****@*****.**"); err != nil { log.Fatal("repo.NewRepoContext(fail to set git user.email): %s", stderr) } else if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil { log.Fatal("repo.NewRepoContext(fail to set git user.name): %s", stderr) } } barePath := path.Join(setting.RepoRootPath, "git-bare.zip") if !com.IsExist(barePath) { data, err := bin.Asset("conf/content/git-bare.zip") if err != nil { log.Fatal("Fail to get asset 'git-bare.zip': %v", err) } else if err := ioutil.WriteFile(barePath, data, os.ModePerm); err != nil { log.Fatal("Fail to write asset 'git-bare.zip': %v", err) } } }
func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. stdout, _, err := com.ExecCmd("git", "config", "--get", "user.name") if err != nil { fmt.Printf("repo.init(fail to get git user.name): %v", err) os.Exit(2) } else if len(stdout) == 0 { if _, _, err = com.ExecCmd("git", "config", "--global", "user.email", "*****@*****.**"); err != nil { fmt.Printf("repo.init(fail to set git user.email): %v", err) os.Exit(2) } else if _, _, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil { fmt.Printf("repo.init(fail to set git user.name): %v", err) os.Exit(2) } } // Initialize illegal patterns. for i := range illegalPatterns[1:] { pattern := "" for j := range illegalPatterns[i+1] { pattern += "[" + string(illegalPatterns[i+1][j]-32) + string(illegalPatterns[i+1][j]) + "]" } illegalPatterns[i+1] = pattern } }
// initRepoCommit temporarily changes with work directory. func initRepoCommit(tmpPath string, sig *git.Signature) error { gitInitLocker.Lock() defer gitInitLocker.Unlock() // Change work directory. curPath, err := os.Getwd() if err != nil { return err } else if err = os.Chdir(tmpPath); err != nil { return err } defer os.Chdir(curPath) var stderr string if _, stderr, err = com.ExecCmd("git", "add", "--all"); err != nil { return err } log.Info("stderr(1): %s", stderr) if _, stderr, err = com.ExecCmd("git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", "Init commit"); err != nil { return err } log.Info("stderr(2): %s", stderr) if _, stderr, err = com.ExecCmd("git", "push", "origin", "master"); err != nil { return err } log.Info("stderr(3): %s", stderr) return nil }
func updateByVcs(vcs, dirPath string) error { err := os.Chdir(dirPath) if err != nil { log.Error("Update by VCS", "Fail to change work directory:") log.Fatal("", "\t"+err.Error()) } defer os.Chdir(workDir) switch vcs { case "git": stdout, _, err := com.ExecCmd("git", "status") if err != nil { log.Error("", "Error occurs when 'git status'") log.Error("", "\t"+err.Error()) } i := strings.Index(stdout, "\n") if i == -1 { log.Error("", "Empty result for 'git status'") return nil } branch := strings.TrimPrefix(stdout[:i], "# On branch ") _, _, err = com.ExecCmd("git", "pull", "origin", branch) if err != nil { log.Error("", "Error occurs when 'git pull origin "+branch+"'") log.Error("", "\t"+err.Error()) } case "hg": _, stderr, err := com.ExecCmd("hg", "pull") if err != nil { log.Error("", "Error occurs when 'hg pull'") log.Error("", "\t"+err.Error()) } if len(stderr) > 0 { log.Error("", "Error: "+stderr) } _, stderr, err = com.ExecCmd("hg", "up") if err != nil { log.Error("", "Error occurs when 'hg up'") log.Error("", "\t"+err.Error()) } if len(stderr) > 0 { log.Error("", "Error: "+stderr) } case "svn": log.Error("", "Error: not support svn yet") } return nil }
func updateByVcs(vcs, dirPath string) error { err := os.Chdir(dirPath) if err != nil { log.Error("Update by VCS", "Fail to change work directory:") log.Fatal("", "\t"+err.Error()) } defer os.Chdir(workDir) switch vcs { case "git": branch, _, err := com.ExecCmd("git", "rev-parse", "--abbrev-ref", "HEAD") if err != nil { log.Error("", "Error occurs when 'git rev-parse --abbrev-ref HEAD'") log.Error("", "\t"+err.Error()) } _, _, err = com.ExecCmd("git", "pull", "origin", branch) if err != nil { log.Error("", "Error occurs when 'git pull origin "+branch+"'") log.Error("", "\t"+err.Error()) } case "hg": _, stderr, err := com.ExecCmd("hg", "pull") if err != nil { log.Error("", "Error occurs when 'hg pull'") log.Error("", "\t"+err.Error()) } if len(stderr) > 0 { log.Error("", "Error: "+stderr) } _, stderr, err = com.ExecCmd("hg", "up") if err != nil { log.Error("", "Error occurs when 'hg up'") log.Error("", "\t"+err.Error()) } if len(stderr) > 0 { log.Error("", "Error: "+stderr) } case "svn": _, stderr, err := com.ExecCmd("svn", "update") if err != nil { log.Error("", "Error occurs when 'svn update'") log.Error("", "\t"+err.Error()) } if len(stderr) > 0 { log.Error("", "Error: "+stderr) } } return nil }
func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. stdout, stderr, err := com.ExecCmd("git", "config", "--get", "user.name") if strings.Contains(stderr, "fatal:") { qlog.Fatalf("repo.NewRepoContext(fail to get git user.name): %s", stderr) } else if err != nil || len(strings.TrimSpace(stdout)) == 0 { if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.email", "*****@*****.**"); err != nil { qlog.Fatalf("repo.NewRepoContext(fail to set git user.email): %s", stderr) } else if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil { qlog.Fatalf("repo.NewRepoContext(fail to set git user.name): %s", stderr) } } }
// Listen starts a SSH server listens on given port. func Listen(port int) { config := &ssh.ServerConfig{ PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key)))) if err != nil { log.Error(3, "SearchPublicKeyByContent: %v", err) return nil, err } return &ssh.Permissions{Extensions: map[string]string{"key-id": com.ToStr(pkey.ID)}}, nil }, } keyPath := filepath.Join(setting.AppDataPath, "ssh/gogs.rsa") if !com.IsExist(keyPath) { os.MkdirAll(filepath.Dir(keyPath), os.ModePerm) _, stderr, err := com.ExecCmd("ssh-keygen", "-f", keyPath, "-t", "rsa", "-N", "") if err != nil { panic(fmt.Sprintf("Fail to generate private key: %v - %s", err, stderr)) } log.Trace("New private key is generateed: %s", keyPath) } privateBytes, err := ioutil.ReadFile(keyPath) if err != nil { panic("Fail to load private key") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { panic("Fail to parse private key") } config.AddHostKey(private) go listen(config, port) }
func getGoogleTags(importPath string, defaultBranch string, isGoRepo bool) []string { stdout, _, err := com.ExecCmd("curl", "http://"+utils.GetProjectPath(importPath)+"/source/browse") if err != nil { return nil } p := []byte(stdout) page := string(p) start := strings.Index(page, "<strong>Tag:</strong>") if start == -1 { return nil } m := googleTagRe.FindAllStringSubmatch(page[start:], -1) var tags []string if isGoRepo { tags = make([]string, 1, 20) } else { tags = make([]string, len(m)+1) } tags[0] = defaultBranch for i, v := range m { if isGoRepo { if strings.HasPrefix(v[1], "go") { tags = append(tags, v[1]) } continue } tags[i+1] = v[1] } return tags }
func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. stdout, _, err := com.ExecCmd("git", "config", "--get", "user.name") if err != nil { fmt.Printf("repo.init(fail to get git user.name): %v", err) os.Exit(2) } else if len(stdout) == 0 { if _, _, err = com.ExecCmd("git", "config", "--global", "user.email", "*****@*****.**"); err != nil { fmt.Printf("repo.init(fail to set git user.email): %v", err) os.Exit(2) } else if _, _, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil { fmt.Printf("repo.init(fail to set git user.name): %v", err) os.Exit(2) } } }
func getGoogleVCS(match map[string]string) error { // Scrape the HTML project page to find the VCS. stdout, _, err := com.ExecCmd("curl", com.Expand("http://code.google.com/p/{repo}/source/checkout", match)) if err != nil { return errors.New("doc.getGoogleVCS(" + match["importPath"] + ") -> " + err.Error()) } m := googleRepoRe.FindSubmatch([]byte(stdout)) if m == nil { return com.NotFoundError{"Could not VCS on Google Code project page."} } match["vcs"] = string(m[1]) return nil }
func makeLink(srcPath, destPath string) error { srcPath = strings.Replace(srcPath, "/", "\\", -1) destPath = strings.Replace(destPath, "/", "\\", -1) // Check if Windows version is XP. if getWindowsVersion() >= 6 { _, stderr, err := com.ExecCmd("cmd", "/c", "mklink", "/j", destPath, srcPath) if err != nil { return errors.New(stderr) } return nil } // XP. setting.IsWindowsXP = true // if both are ntfs file system if volumnType(srcPath) == "NTFS" && volumnType(destPath) == "NTFS" { // if has junction command installed file, err := exec.LookPath("junction") if err == nil { path, _ := filepath.Abs(file) if com.IsFile(path) { _, stderr, err := com.ExecCmd("cmd", "/c", "junction", destPath, srcPath) if err != nil { return errors.New(stderr) } return nil } } } os.RemoveAll(destPath) return com.CopyDir(srcPath, destPath, func(filePath string) bool { return strings.Contains(filePath, setting.VENDOR) }) }
// MigrateRepository migrates a existing repository from other project hosting. func MigrateRepository(user *User, name, desc string, private, mirror bool, url string) (*Repository, error) { repo, err := CreateRepository(user, name, desc, "", "", private, mirror, false) if err != nil { return nil, err } // Clone to temprory path and do the init commit. tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) os.MkdirAll(tmpDir, os.ModePerm) repoPath := RepoPath(user.Name, name) repo.IsBare = false if mirror { if err = MirrorRepository(repo.Id, user.Name, repo.Name, repoPath, url); err != nil { return repo, err } repo.IsMirror = true return repo, UpdateRepository(repo) } // Clone from local repository. _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir) if err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git clone: " + stderr) } // Pull data from source. _, stderr, err = com.ExecCmdDir(tmpDir, "git", "pull", url) if err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git pull: " + stderr) } // Push data to local repository. if _, stderr, err = com.ExecCmdDir(tmpDir, "git", "push", "origin", "master"); err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git push: " + stderr) } return repo, UpdateRepository(repo) }
// MirrorRepository creates a mirror repository from source. func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error { _, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath) if err != nil { return errors.New("git clone --mirror: " + stderr) } if _, err = orm.InsertOne(&Mirror{ RepoId: repoId, RepoName: strings.ToLower(userName + "/" + repoName), Interval: 24, NextUpdate: time.Now().Add(24 * time.Hour), }); err != nil { return err } return git.UnpackRefs(repoPath) }
// GetVersion returns current Git version installed. func GetVersion() (*Version, error) { if gitVer != nil { return gitVer, nil } stdout, stderr, err := com.ExecCmd("git", "version") if err != nil { return nil, errors.New(stderr) } infos := strings.Split(stdout, " ") if len(infos) < 3 { return nil, errors.New("not enough output") } gitVer, err = ParseVersion(infos[2]) return gitVer, err }
func ReloadDocs() error { tocLocker.Lock() defer tocLocker.Unlock() localRoot := setting.Docs.Target // Fetch docs from remote. if setting.Docs.Type.IsRemote() { localRoot = docsRoot absRoot, err := filepath.Abs(localRoot) if err != nil { return fmt.Errorf("filepath.Abs: %v", err) } // Clone new or pull to update. if com.IsDir(absRoot) { stdout, stderr, err := com.ExecCmdDir(absRoot, "git", "pull") if err != nil { return fmt.Errorf("Fail to update docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr) } fmt.Println(stdout) } else { os.MkdirAll(filepath.Dir(absRoot), os.ModePerm) stdout, stderr, err := com.ExecCmd("git", "clone", setting.Docs.Target, absRoot) if err != nil { return fmt.Errorf("Fail to clone docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr) } fmt.Println(stdout) } } if !com.IsDir(localRoot) { return fmt.Errorf("Documentation not found: %s - %s", setting.Docs.Type, localRoot) } tocs, err := initToc(localRoot) if err != nil { return fmt.Errorf("initToc: %v", err) } initDocs(tocs, localRoot) Tocs = tocs return reloadProtects(localRoot) }
// AddPublicKey adds new public key to database and SSH key file. func AddPublicKey(key *PublicKey) (err error) { // Check if public key name has been used. has, err := orm.Get(key) if err != nil { return err } else if has { return ErrKeyAlreadyExist } // Calculate fingerprint. tmpPath := strings.Replace(filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()), "id_rsa.pub"), "\\", "/", -1) os.MkdirAll(path.Dir(tmpPath), os.ModePerm) if err = ioutil.WriteFile(tmpPath, []byte(key.Content), os.ModePerm); err != nil { return err } stdout, _, err := com.ExecCmd("ssh-keygen", "-l", "-f", tmpPath) if err != nil { return err } else if len(stdout) < 2 { return errors.New("Not enough output for calculating fingerprint") } key.Fingerprint = strings.Split(stdout, " ")[1] // Save SSH key. if _, err = orm.Insert(key); err != nil { return err } if err = SaveAuthorizedKeyFile(key); err != nil { if _, err2 := orm.Delete(key); err2 != nil { return err2 } return err } return nil }
// GetVersion returns current Git version installed. func GetVersion() (Version, error) { stdout, stderr, err := com.ExecCmd("git", "version") if err != nil { return Version{}, errors.New(stderr) } infos := strings.Split(stdout, " ") if len(infos) < 3 { return Version{}, errors.New("not enough output") } v := Version{} for i, s := range strings.Split(strings.TrimSpace(infos[2]), ".") { switch i { case 0: v.Major, _ = com.StrTo(s).Int() case 1: v.Minor, _ = com.StrTo(s).Int() case 2: v.Patch, _ = com.StrTo(s).Int() } } return v, nil }
func runExec(ctx *cli.Context) { setup(ctx) if len(ctx.Args()) == 0 { log.Error("exec", "Cannot start command:") log.Fatal("", "\tNo package specified") } installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) // Parse package version. info := ctx.Args()[0] pkgPath := info node := doc.NewNode(pkgPath, pkgPath, doc.BRANCH, "", true) if i := strings.Index(info, "@"); i > -1 { // Specify version by argument. pkgPath = info[:i] node.Type, node.Value = validPath(info[i+1:]) } // Check package name. if !strings.Contains(pkgPath, "/") { pkgPath = doc.GetPkgFullPath(pkgPath) } node.ImportPath = pkgPath node.DownloadURL = pkgPath if len(node.Value) == 0 && com.IsFile(".gopmfile") { // Specify version by gopmfile. gf := doc.NewGopmfile(".") info, err := gf.GetValue("exec", pkgPath) if err == nil && len(info) > 0 { node.Type, node.Value = validPath(info) } } // Check if binary exists. binPath := path.Join(doc.HomeDir, "bins", node.ImportPath, path.Base(node.ImportPath)+versionSuffix(node.Value)) log.Log("Binary path: %s", binPath) if !com.IsFile(binPath) { // Calling bin command. args := []string{"bin", "-d"} if ctx.Bool("verbose") { args = append(args, "-v") } if ctx.Bool("update") { args = append(args, "-u") } args = append(args, node.ImportPath+"@"+node.Type+":"+node.Value) args = append(args, path.Dir(binPath)) stdout, stderr, err := com.ExecCmd("gopm", args...) if err != nil { log.Error("exec", "Building binary failed:") log.Fatal("", "\t"+err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } } fmt.Printf("%+v\n", node) return stdout, stderr, err := com.ExecCmd(binPath, ctx.Args()[1:]...) if err != nil { log.Error("exec", "Calling binary failed:") log.Fatal("", "\t"+err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } }
func getStandardDoc(client *http.Client, importPath, tag, ptag string) (*hv.Package, error) { // hg-higtory: http://go.googlecode.com/hg-history/release/src/pkg/"+importPath+"/" stdout, _, err := com.ExecCmd("curl", "http://go.googlecode.com/hg/src/pkg/"+importPath+"/?r="+tag) if err != nil { return nil, errors.New("doc.getStandardDoc(" + importPath + ") -> " + err.Error()) } p := []byte(stdout) // Check revision tag. var etag string if m := googleRevisionRe.FindSubmatch(p); m == nil { return nil, errors.New("doc.getStandardDoc(" + importPath + ") -> Could not find revision") } else { etag = string(m[1]) if etag == ptag { return nil, errNotModified } } // Get source file data. ms := googleFileRe.FindAllSubmatch(p, -1) files := make([]com.RawFile, 0, len(ms)) for _, m := range ms { fname := strings.Split(string(m[1]), "?")[0] if utils.IsDocFile(fname) { files = append(files, &hv.Source{ SrcName: fname, BrowseUrl: "code.google.com/p/go/source/browse/src/pkg/" + importPath + "/" + fname + "?r=" + tag, RawSrcUrl: "http://go.googlecode.com/hg/src/pkg/" + importPath + "/" + fname + "?r=" + tag, }) } } // Get subdirectories. ms = googleDirRe.FindAllSubmatch(p, -1) dirs := make([]string, 0, len(ms)) for _, m := range ms { dirName := strings.Split(string(m[1]), "?")[0] // Make sure we get directories. if strings.HasSuffix(dirName, "/") && utils.FilterDirName(dirName) { dirs = append(dirs, strings.Replace(dirName, "/", "", -1)) } } if len(files) == 0 && len(dirs) == 0 { return nil, com.NotFoundError{"Directory tree does not contain Go files and subdirs."} } // Fetch file from VCS. if err := fetchGoogleFiles(client, files); err != nil { return nil, err } // Get all tags. tags := getGoogleTags("code.google.com/p/go/"+importPath, "default", true) // Start generating data. w := &hv.Walker{ LineFmt: "#%d", Pdoc: &hv.Package{ PkgInfo: &hv.PkgInfo{ ImportPath: importPath, ProjectName: "Go", ProjectPath: "code.google.com/p/go/source/browse/src/pkg/?r=" + tag, ViewDirPath: "code.google.com/p/go/source/browse/src/pkg/" + importPath + "/?r=" + tag, IsGoRepo: true, Tags: strings.Join(tags, "|||"), Ptag: etag, Vcs: "Google Code", }, PkgDecl: &hv.PkgDecl{ Tag: tag, Dirs: dirs, }, }, } srcs := make([]*hv.Source, 0, len(files)) srcMap := make(map[string]*hv.Source) for _, f := range files { s, _ := f.(*hv.Source) srcs = append(srcs, s) if len(tag) == 0 && !strings.HasSuffix(f.Name(), "_test.go") { srcMap[f.Name()] = s } } pdoc, err := w.Build(&hv.WalkRes{ WalkDepth: hv.WD_All, WalkType: hv.WT_Memory, WalkMode: hv.WM_All, Srcs: srcs, }) if err != nil { return nil, errors.New("doc.getStandardDoc(" + importPath + ") -> Fail to build: " + err.Error()) } return pdoc, generateHv(importPath, srcMap) }
func getGoogleDoc(client *http.Client, match map[string]string, tag, ptag string) (*hv.Package, error) { setupGoogleMatch(match) if m := googleEtagRe.FindStringSubmatch(ptag); m != nil { match["vcs"] = m[1] } else if err := getGoogleVCS(match); err != nil { return nil, err } match["tag"] = tag // Scrape the repo browser to find the project revision and individual Go files. stdout, _, err := com.ExecCmd("curl", com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}{dir}/?r={tag}", match)) if err != nil { return nil, errors.New("doc.getGoogleDoc(" + match["importPath"] + ") -> " + err.Error()) } p := []byte(stdout) // Check revision tag. var etag string if m := googleRevisionRe.FindSubmatch(p); m == nil { return nil, errors.New("doc.getGoogleDoc(" + match["importPath"] + ") -> Could not find revision") } else { etag = string(m[1]) if etag == ptag { return nil, errNotModified } } match["browserUrlTpl"] = "code.google.com/p/{repo}/source/browse{dir}/{0}?repo={subrepo}&r={tag}" match["rawSrcUrlTpl"] = "http://{subrepo}{dot}{repo}.googlecode.com/{vcs}{dir}/{0}?r={tag}" var isGoPro bool var files []com.RawFile var dirs []string // Unrecord and non-SVN project can download archive. if len(ptag) == 0 || match["vcs"] == "svn" { tmpTag := match["tag"] if len(tmpTag) == 0 { tmpTag = defaultTags[match["vcs"]] } isGoPro, _, files, dirs, err = getRepoByArchive(match, com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/archive/{0}.zip", match, tmpTag)) if err != nil { return nil, errors.New("doc.getGoogleDoc(" + match["importPath"] + ") -> Fail to download archive: " + err.Error()) } } else { // Get source file data. ms := googleFileRe.FindAllSubmatch(p, -1) files = make([]com.RawFile, 0, len(ms)) for _, m := range ms { fname := strings.Split(string(m[1]), "?")[0] if utils.IsDocFile(fname) { isGoPro = true files = append(files, &hv.Source{ SrcName: fname, BrowseUrl: com.Expand(match["browserUrlTpl"], match, fname), RawSrcUrl: com.Expand(match["rawSrcUrlTpl"], match, fname), }) } } // Get subdirectories. ms = googleDirRe.FindAllSubmatch(p, -1) dirs = make([]string, 0, len(ms)) for _, m := range ms { dirName := strings.Split(string(m[1]), "?")[0] // Make sure we get directories. if strings.HasSuffix(dirName, "/") && utils.FilterDirName(dirName) { dirs = append(dirs, strings.Replace(dirName, "/", "", -1)) } } } if !isGoPro { return nil, com.NotFoundError{"Cannot find Go files, it's not a Go project."} } if len(files) == 0 && len(dirs) == 0 { return nil, com.NotFoundError{"Directory tree does not contain Go files and subdirs."} } // Fetch file from VCS. if err := fetchGoogleFiles(client, files); err != nil { return nil, err } // Get all tags. tags := getGoogleTags(match["importPath"], defaultTags[match["vcs"]], false) // Start generating data. w := &hv.Walker{ LineFmt: "#%d", Pdoc: &hv.Package{ PkgInfo: &hv.PkgInfo{ ImportPath: match["importPath"], IsGoSubrepo: utils.IsGoSubrepoPath(strings.TrimPrefix( match["importPath"], "code.google.com/p/")), ProjectName: com.Expand("{repo}{dot}{subrepo}", match), ProjectPath: com.Expand("code.google.com/p/{repo}/source/browse/?repo={subrepo}&r={tag}", match), ViewDirPath: com.Expand("code.google.com/p/{repo}/source/browse{dir}?repo={subrepo}&r={tag}", match), Tags: strings.Join(tags, "|||"), Ptag: etag, Vcs: "Google Code", }, PkgDecl: &hv.PkgDecl{ Tag: tag, Dirs: dirs, }, }, } srcs := make([]*hv.Source, 0, len(files)) srcMap := make(map[string]*hv.Source) for _, f := range files { s, _ := f.(*hv.Source) srcs = append(srcs, s) if len(tag) == 0 && (w.Pdoc.IsGoSubrepo || w.Pdoc.IsCmd) && !strings.HasSuffix(f.Name(), "_test.go") { srcMap[f.Name()] = s } } pdoc, err := w.Build(&hv.WalkRes{ WalkDepth: hv.WD_All, WalkType: hv.WT_Memory, WalkMode: hv.WM_All, Srcs: srcs, }) if err != nil { return nil, errors.New("doc.getGoogleDoc(" + match["importPath"] + ") -> Fail to build: " + err.Error()) } if len(tag) == 0 && (w.Pdoc.IsGoSubrepo || w.Pdoc.IsCmd) { err = generateHv(match["importPath"], srcMap) } return pdoc, err }
// InitRepository initializes README and .gitignore if needed. func initRepository(f string, user *User, repo *Repository, initReadme bool, repoLang, license string) error { repoPath := RepoPath(user.Name, repo.Name) // Create bare new repository. if err := extractGitBareZip(repoPath); err != nil { return err } // hook/post-update pu, err := os.OpenFile(filepath.Join(repoPath, "hooks", "post-update"), os.O_CREATE|os.O_WRONLY, 0777) if err != nil { return err } defer pu.Close() // TODO: Windows .bat if _, err = pu.WriteString(fmt.Sprintf("#!/usr/bin/env bash\n%s update\n", appPath)); err != nil { return err } // hook/post-update pu2, err := os.OpenFile(filepath.Join(repoPath, "hooks", "post-receive"), os.O_CREATE|os.O_WRONLY, 0777) if err != nil { return err } defer pu2.Close() // TODO: Windows .bat if _, err = pu2.WriteString("#!/usr/bin/env bash\ngit update-server-info\n"); err != nil { return err } // Initialize repository according to user's choice. fileName := map[string]string{} if initReadme { fileName["readme"] = "README.md" } if repoLang != "" { fileName["gitign"] = ".gitignore" } if license != "" { fileName["license"] = "LICENSE" } // Clone to temprory path and do the init commit. tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) os.MkdirAll(tmpDir, os.ModePerm) if _, _, err := com.ExecCmd("git", "clone", repoPath, tmpDir); err != nil { return err } // README if initReadme { defaultReadme := repo.Name + "\n" + strings.Repeat("=", utf8.RuneCountInString(repo.Name)) + "\n\n" + repo.Description if err := ioutil.WriteFile(filepath.Join(tmpDir, fileName["readme"]), []byte(defaultReadme), 0644); err != nil { return err } } // .gitignore if repoLang != "" { filePath := "conf/gitignore/" + repoLang if com.IsFile(filePath) { if _, err := com.Copy(filePath, filepath.Join(tmpDir, fileName["gitign"])); err != nil { return err } } } // LICENSE if license != "" { filePath := "conf/license/" + license if com.IsFile(filePath) { if _, err := com.Copy(filePath, filepath.Join(tmpDir, fileName["license"])); err != nil { return err } } } if len(fileName) == 0 { return nil } // Apply changes and commit. if err := initRepoCommit(tmpDir, user.NewGitSig()); err != nil { return err } return nil }
func getGihubTokenFromConfig() string { stdout, _, _ := com.ExecCmd("git", "config", "--global", "github.token") return strings.TrimSpace(stdout) }
// InitRepository initializes README and .gitignore if needed. func initRepository(f string, user *User, repo *Repository, initReadme bool, repoLang, license string) error { repoPath := RepoPath(user.Name, repo.Name) // Create bare new repository. if err := extractGitBareZip(repoPath); err != nil { return err } rp := strings.NewReplacer("\\", "/", " ", "\\ ") // hook/post-update if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"), fmt.Sprintf("#!/usr/bin/env %s\n%s update $1 $2 $3\n", base.ScriptType, rp.Replace(appPath))); err != nil { return err } // Initialize repository according to user's choice. fileName := map[string]string{} if initReadme { fileName["readme"] = "README.md" } if repoLang != "" { fileName["gitign"] = ".gitignore" } if license != "" { fileName["license"] = "LICENSE" } // Clone to temprory path and do the init commit. tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) os.MkdirAll(tmpDir, os.ModePerm) _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir) if err != nil { return errors.New("git clone: " + stderr) } // README if initReadme { defaultReadme := repo.Name + "\n" + strings.Repeat("=", utf8.RuneCountInString(repo.Name)) + "\n\n" + repo.Description if err := ioutil.WriteFile(filepath.Join(tmpDir, fileName["readme"]), []byte(defaultReadme), 0644); err != nil { return err } } // .gitignore if repoLang != "" { filePath := "conf/gitignore/" + repoLang if com.IsFile(filePath) { if err := com.Copy(filePath, filepath.Join(tmpDir, fileName["gitign"])); err != nil { return err } } } // LICENSE if license != "" { filePath := "conf/license/" + license if com.IsFile(filePath) { if err := com.Copy(filePath, filepath.Join(tmpDir, fileName["license"])); err != nil { return err } } } if len(fileName) == 0 { return nil } SetRepoEnvs(user.Id, user.Name, repo.Name) // Apply changes and commit. return initRepoCommit(tmpDir, user.NewGitSig()) }
func runUpdate(ctx *cli.Context) { setup(ctx) isAnythingUpdated := false // Load local version info. localVerInfo := loadLocalVerInfo() // Get remote version info. var remoteVerInfo version if err := com.HttpGetJSON(http.DefaultClient, "http://gopm.io/VERSION.json", &remoteVerInfo); err != nil { log.Error("Update", "Fail to fetch VERSION.json") log.Fatal("", err.Error()) } // Package name list. if remoteVerInfo.PackageNameList > localVerInfo.PackageNameList { log.Log("Updating pkgname.list...%v > %v", localVerInfo.PackageNameList, remoteVerInfo.PackageNameList) data, err := com.HttpGetBytes(http.DefaultClient, "https://raw2.github.com/gpmgo/docs/master/pkgname.list", nil) if err != nil { log.Error("Update", "Fail to update pkgname.list") log.Fatal("", err.Error()) } if err = com.WriteFile(path.Join(doc.HomeDir, doc.PKG_NAME_LIST_PATH), data); err != nil { log.Error("Update", "Fail to save pkgname.list") log.Fatal("", err.Error()) } log.Log("Update pkgname.list to %v succeed!", remoteVerInfo.PackageNameList) isAnythingUpdated = true } // Gopm. if remoteVerInfo.Gopm > localVerInfo.Gopm { log.Log("Updating gopm...%v > %v", localVerInfo.Gopm, remoteVerInfo.Gopm) installRepoPath = doc.HomeDir + "/repos" tmpDirPath := filepath.Join(doc.HomeDir, "temp") tmpBinPath := filepath.Join(tmpDirPath, "gopm") if runtime.GOOS == "windows" { tmpBinPath += ".exe" } os.MkdirAll(tmpDirPath, os.ModePerm) os.Remove(tmpBinPath) // Fetch code. args := []string{"bin", "-u", "-d"} if ctx.Bool("verbose") { args = append(args, "-v") } args = append(args, []string{"github.com/gpmgo/gopm", tmpDirPath}...) stdout, stderr, err := com.ExecCmd("gopm", args...) if err != nil { log.Error("Update", "Fail to execute 'gopm bin -u -d github.com/gpmgo/gopm "+tmpDirPath+"'") log.Fatal("", err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } // Check if previous steps were successful. if !com.IsExist(tmpBinPath) { log.Error("Update", "Fail to continue command") log.Fatal("", "Previous steps weren't successful, no binary produced") } movePath := exePath() log.Log("New binary will be replaced for %s", movePath) // Move binary to given directory. if runtime.GOOS != "windows" { err := os.Rename(tmpBinPath, movePath) if err != nil { log.Error("Update", "Fail to move binary") log.Fatal("", err.Error()) } os.Chmod(movePath+"/"+path.Base(tmpBinPath), os.ModePerm) } else { batPath := filepath.Join(tmpDirPath, "update.bat") f, err := os.Create(batPath) if err != nil { log.Error("Update", "Fail to generate bat file") log.Fatal("", err.Error()) } f.WriteString("@echo off\r\n") f.WriteString(fmt.Sprintf("ping -n 1 127.0.0.1>nul\r\ncopy \"%v\" \"%v\" >nul\r\ndel \"%v\" >nul\r\n\r\n", tmpBinPath, movePath, tmpBinPath)) //f.WriteString(fmt.Sprintf("del \"%v\"\r\n", batPath)) f.Close() attr := &os.ProcAttr{ Dir: workDir, Env: os.Environ(), Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, } _, err = os.StartProcess(batPath, []string{batPath}, attr) if err != nil { log.Error("Update", "Fail to start bat process") log.Fatal("", err.Error()) } } log.Success("SUCC", "Update", "Command execute successfully!") isAnythingUpdated = true } // Save JSON. f, err := os.Create(path.Join(doc.HomeDir, doc.VER_PATH)) if err != nil { log.Error("Update", "Fail to create VERSION.json") log.Fatal("", err.Error()) } if err := json.NewEncoder(f).Encode(&remoteVerInfo); err != nil { log.Error("Update", "Fail to encode VERSION.json") log.Fatal("", err.Error()) } if !isAnythingUpdated { log.Log("Nothing need to be updated") } log.Log("Exit old gopm") }
// Only support .zip. func getRepoByArchive(match map[string]string, downloadPath string) (bool, string, []com.RawFile, []string, error) { stdout, _, err := com.ExecCmd("curl", downloadPath) if err != nil { return false, "", nil, nil, err } p := []byte(stdout) r, err := zip.NewReader(bytes.NewReader(p), int64(len(p))) if err != nil { return false, "", nil, nil, errors.New(downloadPath + " -> new zip: " + err.Error()) } if len(r.File) == 0 { return false, "", nil, nil, nil } nameLen := strings.Index(r.File[0].Name, "/") dirPrefix := match["dir"] if len(dirPrefix) != 0 { dirPrefix = dirPrefix[1:] + "/" } preLen := len(dirPrefix) isGoPro := false // for k, v := range match { // println(k, v) // } comment := r.Comment files := make([]com.RawFile, 0, 5) dirs := make([]string, 0, 5) for _, f := range r.File { fileName := f.Name[nameLen+1:] // Skip directories and files in wrong directories, get them later. if strings.HasSuffix(fileName, "/") || !strings.HasPrefix(fileName, dirPrefix) { continue } //fmt.Println(fileName) // Get files and check if directories have acceptable files. if d, fn := path.Split(fileName); utils.IsDocFile(fn) && utils.FilterDirName(d) { // Check if it's a Go file. if !isGoPro && strings.HasSuffix(fn, ".go") { isGoPro = true } // Check if file is in the directory that is corresponding to import path. if d == dirPrefix { // Yes. if !isGoPro && strings.HasSuffix(fn, ".go") { isGoPro = true } // Get file from archive. rc, err := f.Open() if err != nil { return isGoPro, comment, files, dirs, errors.New(downloadPath + " -> open file: " + err.Error()) } p := make([]byte, f.FileInfo().Size()) rc.Read(p) if err != nil { return isGoPro, comment, files, dirs, errors.New(downloadPath + " -> read file: " + err.Error()) } //fmt.Println(com.Expand(match["browserUrlTpl"], match, fn)) files = append(files, &hv.Source{ SrcName: fn, BrowseUrl: com.Expand(match["browserUrlTpl"], match, fn), RawSrcUrl: com.Expand(match["rawSrcUrlTpl"], match, fileName[preLen:]), SrcData: p, }) } else { sd, _ := path.Split(d[preLen:]) sd = strings.TrimSuffix(sd, "/") if !checkDir(sd, dirs) { dirs = append(dirs, sd) } } } } return isGoPro, comment, files, dirs, nil }
func ExampleExecCmd() { stdout, stderr, err := com.ExecCmd("go", "help", "get") fmt.Println(stdout, stderr, err) }
func main() { flag.Usage = usage flag.Parse() // SetLog() // defer log4go.Close() args := flag.Args() argnums := flag.NArg() if flag.NArg() < 1 && flag.NFlag() < 1 { usage() } if argnums >= 1 { switch args[0] { case "help": usage() case "version": version() os.Exit(2) case "&", "|", "<", ">": default: if args[argnums-1] == "&" { args = args[:argnums-1] } } } var err error if *infile == "" { fmt.Println("please input your infile which included 'hostaddr username password command' one per line") usage() } else if !com.IsExist(*infile) { fmt.Printf("not found input file: %s\n", *infile) usage() } if *cfg == "" { gCfg = "./mssh.conf" } else { gCfg = *cfg } if !parseconf(gCfg) { fmt.Printf("init conf file %s failed, exit\n", *cfg) os.Exit(2) } if *cmd != "" { if len(args) > 0 { gCommand = fmt.Sprintf("%s %s", *cmd, strings.Join(args, " ")) } else { if *shellmode { curpath, _ := os.Getwd() if !strings.Contains(*cmd, "/") { *cmd = curpath + "/" + *cmd } gCommand = fmt.Sprintf("%s %s", "/bin/bash", *cmd) } else { gCommand = *cmd } } } gCommand = helper.Abs(gCommand) vprintf("gCommnad: %s\n", gCommand) vprintf("gUsername: %s\n", gUsername) vprintf("gPassword: %s\n", gPassword) vprintf("gTimeout: %v\n", gTimeout) sshobjs, err := parse(*infile) if err != nil { log.Fatal(err) } vprintf("%#v\n", sshobjs) if *n < 1 || *n > 10000 { *n = runtime.NumCPU() } cmdout, _, err := com.ExecCmd("logname") vprintf("cmdout: %s", cmdout) if err == nil { cmdout = strings.TrimSpace(cmdout) if len(gMaillist) == 0 { gMaillist = fmt.Sprintf("*****@*****.**", cmdout) } } vprintf("gMaillist: %s\n", gMaillist) // basename := filepath.Base(*cmd) var r = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_") randomfname := string(helper.RandomCreateBytes(32, r...)) + ".sh" vprintf("randomfname: %s\n", randomfname) chFirst := make(chan SshClient, *n) // chSecond := make(chan SshClient, *n) oldtime := time.Now() scpTout := fmt.Sprintf("ConnectTimeout=%d", gTimeout) go func() { defer close(chFirst) for i, _ := range sshobjs { if *israndompwd { sshobjs[i].Cmd = fmt.Sprintf("echo %s | passwd --stdin %s", sshobjs[i].Password, sshobjs[i].Username) vprintf("%#v\n", sshobjs[i]) } else if *shellmode { com.ExecCmd("scp", "-o", scpTout, "-o", "BatchMode=yes", "-r", *cmd, fmt.Sprintf("%s:/tmp/%s", helper.GetHost(sshobjs[i].Hostaddr, ":"), randomfname)) sshobjs[i].Cmd = fmt.Sprintf("/bin/bash /tmp/%s && /bin/rm -f /tmp/%s", randomfname, randomfname) vprintf("%#v\n", sshobjs[i]) } chFirst <- sshobjs[i] } }() wg1 := new(sync.WaitGroup) wg2 := new(sync.WaitGroup) tryslice := make([]SshClient, 0) sem := make(chan struct{}, *n) mux := new(sync.Mutex) for i := 0; i < *n; i++ { wg1.Add(1) go func(ch chan SshClient) { defer wg1.Done() for v := range ch { vprintf("%#v\n", v) func(sshitem SshClient) { err, _, stdout, _ := sshutils.SshExec(sshitem.Hostaddr, sshitem.Username, sshitem.Password, sshitem.Cmd, gTimeout) if err != nil { mux.Lock() tryslice = append(tryslice, sshitem) mux.Unlock() return } mux.Lock() cnt++ fmt.Println(strings.Repeat("*", 40), "[", cnt, "]", strings.Repeat("*", 40)) fmt.Println(fmt.Sprintf("%s:\n%s\n", sshitem.Hostaddr, stdout)) mux.Unlock() }(v) } }(chFirst) } wg1.Wait() //for /usr/bin/ssh execute shell cmds buf.WriteString("\nrunning results(error host lists):\n\n") for _, v := range tryslice { sem <- struct{}{} wg2.Add(1) go func(sshitem SshClient) { defer wg2.Done() err, _, stdout, _ := sshutils.SshCmdExec(sshitem.Hostaddr, sshitem.Username, sshitem.Password, sshitem.Cmd, gTimeout) if err != nil { log.Println("[/usr/bin/ssh]", sshitem.Hostaddr, err) // log4go.Error("[/usr/bin/ssh] %s %v", sshitem.Hostaddr, err) buf.WriteString(sshitem.Hostaddr + "\n") <-sem return } mux.Lock() cnt++ fmt.Println("[", cnt, "]", strings.Repeat("*", 80)) fmt.Println(fmt.Sprintf("%s %s:\n%s\n", "[/usr/bin/ssh]", sshitem.Hostaddr, stdout)) // log4go.Info(fmt.Sprintf("%s %s:\n%s\n", "[/usr/bin/ssh]", sshitem.Hostaddr, stdout)) mux.Unlock() <-sem }(v) } wg2.Wait() //kill ssh process which is timeout vprintf("Kill ssh for timeout\n") kill(sshutils.Cmds) errMsg := buf.String() htmlErrMsg := strings.Replace(errMsg, "\n", "<br>", -1) now := time.Now().String() title := gTitle mode := gMode execTime := time.Since(oldtime) totalTime := execTime.String() var body string if mode == "html" { body = now + "<br>" + gBody + "<br>" + htmlErrMsg + "<br>total time: " + totalTime } else { body = now + "\n" + gBody + "\n" + errMsg + "\ntotal time: " + totalTime } maillist := []string{gMaillist} config := fmt.Sprintf(`{"username":"******","password":"******","host":"%s","port":%d}`, mailUsername, mailPassword, mailHost, mailPort) mail := utils.NewEMail(config) mail.To = maillist mail.From = gFr_addr mail.Subject = title if mode == "html" { mail.HTML = body } else { mail.Text = body } if *ismail { err = mail.Send() if err != nil { log.Println("send mail failed:", err) goto LEAVE } fmt.Println("send mail successful") } LEAVE: newtime := time.Since(oldtime) fmt.Println("run time:", newtime) }
func runUpdate(ctx *cli.Context) { doc.LoadPkgNameList(doc.HomeDir + "/data/pkgname.list") installRepoPath = doc.HomeDir + "/repos" // Check arguments. num := 0 if len(ctx.Args()) != num { log.Error("Update", "Fail to start command") log.Fatal("", "Invalid argument number") } // Parse package version. info := "github.com/gpmgo/gopm" pkgPath := info ver := "" var err error if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] _, ver = validPath(info[i+1:]) } // Check package name. if !strings.Contains(pkgPath, "/") { name, ok := doc.PackageNameList[pkgPath] if !ok { log.Error("Update", "Invalid package name: "+pkgPath) log.Fatal("", "No match in the package name list") } pkgPath = name } // Get code. stdout, _, _ := com.ExecCmd("gopm", "get", info) if len(stdout) > 0 { fmt.Print(stdout) } // Check if previous steps were successful. repoPath := installRepoPath + "/" + pkgPath if len(ver) > 0 { repoPath += "." + ver } if !com.IsDir(repoPath) { log.Error("Bin", "Fail to continue command") log.Fatal("", "Previous steps weren't successful") } wd, err := os.Getwd() if err != nil { log.Error("Bin", "Fail to get work directory") log.Fatal("", err.Error()) } // Change to repository path. log.Log("Changing work directory to %s", repoPath) err = os.Chdir(repoPath) if err != nil { log.Error("Bin", "Fail to change work directory") log.Fatal("", err.Error()) } // Build application. stdout, _, _ = com.ExecCmd("gopm", "build") if len(stdout) > 0 { fmt.Print(stdout) } defer func() { // Clean files. os.RemoveAll(path.Join(repoPath, doc.VENDOR)) }() // Check if previous steps were successful. if com.IsFile(doc.GOPM_FILE_NAME) { log.Trace("Loading gopmfile...") gf := doc.NewGopmfile(".") var err error pkgName, err = gf.GetValue("target", "path") if err == nil { log.Log("Target name: %s", pkgName) } } if len(pkgName) == 0 { _, pkgName = filepath.Split(pkgPath) } binName := path.Base(pkgName) if runtime.GOOS == "windows" { binName += ".exe" } binPath := path.Join(doc.VENDOR, "src", pkgPath, binName) if !com.IsFile(binPath) { log.Error("Update", "Fail to continue command") log.Fatal("", "Previous steps weren't successful or the project does not contain main package") } movePath := exePath() fmt.Print(movePath) // Move binary to given directory. if runtime.GOOS != "windows" { err = os.Rename(binPath, movePath) if err != nil { log.Error("Update", "Fail to move binary") log.Fatal("", err.Error()) } os.Chmod(movePath+"/"+binName, os.ModePerm) } else { batPath := filepath.Join(wd, "a.bat") f, err := os.Create(batPath) if err != nil { log.Error("Update", "Fail to generate bat file") log.Fatal("", err.Error()) } f.WriteString(fmt.Sprintf(`ping -n 1 127.0.0.1>nul\ncopy "%v" "%v"\ndel "%v"\ndel "%v"`, binPath, movePath, binPath, batPath)) f.Close() attr := &os.ProcAttr{ Dir: wd, Env: os.Environ(), //Files: []*os.File{nil, nil, nil}, Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, } _, err = os.StartProcess(batPath, []string{"a.bat"}, attr) if err != nil { log.Error("Update", "Fail to start bat process") log.Fatal("", err.Error()) } } log.Log("Changing work directory back to %s", wd) os.Chdir(wd) log.Success("SUCC", "Update", "Command execute successfully!") }