瀏覽代碼

Merge pull request #447 from Morganamilo/fix#131

Implement diffs for pkgbuild viewing.
Anna 7 年之前
父節點
當前提交
5b6c4101f8
共有 5 個文件被更改,包括 137 次插入20 次删除
  1. 23 1
      cmd.go
  2. 2 0
      config.go
  3. 17 1
      download.go
  4. 93 18
      install.go
  5. 2 0
      utils.go

+ 23 - 1
cmd.go

@@ -304,6 +304,10 @@ func handleConfig(option, value string) bool {
 		config.PGPFetch = true
 	case "nopgpfetch":
 		config.PGPFetch = false
+	case "showdiffs":
+		config.ShowDiffs = true
+	case "noshowdiffs":
+		config.ShowDiffs = false
 	case "a", "aur":
 		mode = ModeAUR
 	case "repo":
@@ -603,7 +607,6 @@ func passToMakepkgCapture(dir string, args ...string) (string, string, error) {
 	args = append(args, mflags...)
 
 	cmd := exec.Command(config.MakepkgBin, args...)
-	cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
 	cmd.Dir = dir
 	cmd.Stdout = &outbuf
 	cmd.Stderr = &errbuf
@@ -630,3 +633,22 @@ func passToGit(dir string, _args ...string) (err error) {
 	err = cmd.Run()
 	return
 }
+
+func passToGitCapture(dir string, _args ...string) (string, string, error) {
+	var outbuf, errbuf bytes.Buffer
+	gitflags := strings.Fields(config.GitFlags)
+	args := []string{"-C", dir}
+	args = append(args, gitflags...)
+	args = append(args, _args...)
+
+	cmd := exec.Command(config.GitBin, args...)
+	cmd.Dir = dir
+	cmd.Stdout = &outbuf
+	cmd.Stderr = &errbuf
+
+	err := cmd.Run()
+	stdout := outbuf.String()
+	stderr := errbuf.String()
+
+	return stdout, stderr, err
+}

+ 2 - 0
config.go

@@ -64,6 +64,7 @@ type Configuration struct {
 	GitClone      bool   `json:"gitclone"`
 	Provides      bool   `json:"provides"`
 	PGPFetch      bool   `json:"pgpfetch"`
+	ShowDiffs     bool   `json:"showdifs"`
 }
 
 var version = "5.688"
@@ -167,6 +168,7 @@ func defaultSettings(config *Configuration) {
 	config.AnswerUpgrade = ""
 	config.GitClone = true
 	config.Provides = true
+	config.ShowDiffs = true
 }
 
 // Editor returns the preferred system editor.

+ 17 - 1
download.go

@@ -7,6 +7,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"strings"
 )
 
 // Decide what download method to use:
@@ -20,7 +21,7 @@ func shouldUseGit(path string) bool {
 	}
 
 	_, err = os.Stat(filepath.Join(path, ".git"))
-	return os.IsExist(err)
+	return err == nil || os.IsExist(err)
 }
 
 func downloadFile(path string, url string) (err error) {
@@ -43,6 +44,15 @@ func downloadFile(path string, url string) (err error) {
 	return err
 }
 
+func gitGetHash(path string, name string) (string, error) {
+	stdout, stderr, err := passToGitCapture(filepath.Join(path, name), "rev-parse", "HEAD")
+	if err != nil {
+		return "", fmt.Errorf("%s%s", stderr, err)
+	}
+
+	return strings.TrimSpace(stdout), nil
+}
+
 func gitDownload(url string, path string, name string) error {
 	_, err := os.Stat(filepath.Join(path, name, ".git"))
 	if os.IsNotExist(err) {
@@ -74,6 +84,12 @@ func gitDownload(url string, path string, name string) error {
 	return nil
 }
 
+func gitDiff(path string, name string) error {
+	err := passToGit(filepath.Join(path, name), "diff", "HEAD..HEAD@{upstream}")
+
+	return err
+}
+
 // DownloadAndUnpack downloads url tgz and extracts to path.
 func downloadAndUnpack(url string, path string) (err error) {
 	err = os.MkdirAll(path, 0755)

+ 93 - 18
install.go

@@ -153,13 +153,17 @@ func install(parser *arguments) error {
 
 		cleanBuilds(toClean)
 
-		err = downloadPkgBuilds(do.Aur, parser.targets, do.Bases)
+		oldHashes, err := downloadPkgBuilds(do.Aur, parser.targets, do.Bases)
 		if err != nil {
 			return err
 		}
 
 		if len(toEdit) > 0 {
-			err = editPkgBuilds(toEdit)
+			if config.ShowDiffs {
+				err = showPkgBuildDiffs(toEdit, do.Bases, oldHashes)
+			} else {
+				err = editPkgBuilds(toEdit, do.Bases, oldHashes)
+			}
 			if err != nil {
 				return err
 			}
@@ -422,7 +426,11 @@ func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed
 		}
 	}
 
-	fmt.Println(bold(green(arrow + " PKGBUILDs to edit?")))
+	if config.ShowDiffs {
+		fmt.Println(bold(green(arrow + " Diffs to show?")))
+	} else {
+		fmt.Println(bold(green(arrow + " PKGBUILDs to edit?")))
+	}
 	fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)"))
 
 	fmt.Print(bold(green(arrow + " ")))
@@ -481,20 +489,66 @@ func cleanBuilds(pkgs []*rpc.Pkg) {
 	}
 }
 
-func editPkgBuilds(pkgs []*rpc.Pkg) error {
+func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error {
+	for _, pkg := range pkgs {
+		dir := filepath.Join(config.BuildDir, pkg.PackageBase)
+		if shouldUseGit(dir) {
+			hash, _ := hashes[pkg.PackageBase]
+			if hash == "" {
+				hash = gitEmptyTree
+			}
+
+			head, err := gitGetHash(config.BuildDir, pkg.PackageBase)
+			if err != nil {
+				return err
+			}
+
+			if head == hash {
+				fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping"))
+				continue
+			}
+
+			args := []string{"diff", hash + "..HEAD", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"}
+			if useColor {
+				args = append(args, "--color=always")
+			} else {
+				args = append(args, "--color=never")
+			}
+			err = passToGit(dir, args...)
+			if err != nil {
+				return err
+			}
+		} else {
+			editor, editorArgs := editor()
+			editorArgs = append(editorArgs, filepath.Join(dir, "PKGBUILD"))
+			editcmd := exec.Command(editor, editorArgs...)
+			editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+			err := editcmd.Run()
+			if err != nil {
+				return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err)
+			}
+		}
+	}
+
+	return nil
+}
+
+func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error {
 	pkgbuilds := make([]string, 0, len(pkgs))
 	for _, pkg := range pkgs {
 		dir := filepath.Join(config.BuildDir, pkg.PackageBase)
 		pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD"))
 	}
 
-	editor, editorArgs := editor()
-	editorArgs = append(editorArgs, pkgbuilds...)
-	editcmd := exec.Command(editor, editorArgs...)
-	editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
-	err := editcmd.Run()
-	if err != nil {
-		return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err)
+	if len(pkgbuilds) > 0 {
+		editor, editorArgs := editor()
+		editorArgs = append(editorArgs, pkgbuilds...)
+		editcmd := exec.Command(editor, editorArgs...)
+		editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+		err := editcmd.Run()
+		if err != nil {
+			return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err)
+		}
 	}
 
 	return nil
@@ -535,8 +589,11 @@ func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD,
 	}
 }
 
-func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*rpc.Pkg) error {
-	for k, pkg := range pkgs {
+func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*rpc.Pkg) (map[string]string, error) {
+	toSkip := make(stringSet)
+	hashes := make(map[string]string)
+
+	for _, pkg := range pkgs {
 		if config.ReDownload == "no" || (config.ReDownload == "yes" && !targets.get(pkg.Name)) {
 			dir := filepath.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO")
 			pkgbuild, err := gopkg.ParseSRCINFO(dir)
@@ -546,13 +603,28 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r
 				versionPKG, errP := gopkg.NewCompleteVersion(pkgbuild.Version())
 				if errP == nil && errR == nil {
 					if !versionRPC.Newer(versionPKG) {
-						str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n")
-						fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases)))
-						continue
+						toSkip.set(pkg.PackageBase)
 					}
 				}
 			}
 		}
+	}
+
+	for k, pkg := range pkgs {
+		if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) {
+			hash, err := gitGetHash(config.BuildDir, pkg.PackageBase)
+			if err == nil {
+				hashes[pkg.PackageBase] = hash
+			} else {
+				hashes[pkg.PackageBase] = ""
+			}
+		}
+
+		if toSkip.get(pkg.PackageBase) {
+			str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n")
+			fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases)))
+			continue
+		}
 
 		str := bold(cyan("::") + " Downloading PKGBUILD (%d/%d): %s\n")
 
@@ -561,15 +633,18 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r
 		var err error
 		if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) {
 			err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase)
+			if err != nil {
+				return hashes, err
+			}
 		} else {
 			err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir)
 		}
 		if err != nil {
-			return err
+			return hashes, err
 		}
 	}
 
-	return nil
+	return hashes, nil
 }
 
 func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) {

+ 2 - 0
utils.go

@@ -5,6 +5,8 @@ import (
 	"unicode"
 )
 
+const gitEmptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
+
 type mapStringSet map[string]stringSet
 
 type intRange struct {