Merge pull request #206 from Morganamilo/lsremote

Use git ls-remote to track devel updates
This commit is contained in:
Morgana 2018-03-06 23:55:37 +00:00 committed by GitHub
commit 251d31c970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 197 additions and 178 deletions

View file

@ -4,16 +4,19 @@ package main
// RemovePackage removes package from VCS information
func removeVCSPackage(pkgs []string) {
updated := false
for _, pkgName := range pkgs {
for i, e := range savedInfo {
if e.Package == pkgName {
savedInfo[i] = savedInfo[len(savedInfo)-1]
savedInfo = savedInfo[:len(savedInfo)-1]
}
_, ok := savedInfo[pkgName]
if ok {
delete(savedInfo, pkgName)
updated = true
}
}
_ = saveVCSInfo()
if updated {
saveVCSInfo()
}
}
// CleanDependencies removes all dangling dependencies in system

10
cmd.go
View file

@ -90,9 +90,9 @@ func initYay() (err error) {
cacheHome = os.Getenv("HOME") + "/.cache/yay"
}
configFile = configHome + "/config.json"
vcsFile = configHome + "/yay_vcs.json"
completionFile = cacheHome + "/aur_"
configFile = configHome + "/" + configFileName
vcsFile = cacheHome + "/" + vcsFileName
completionFile = cacheHome + "/" + completionFilePrefix
////////////////
// yay config //
@ -420,10 +420,6 @@ func handleYay() (err error) {
if err != nil {
return
}
err = saveVCSInfo()
if err != nil {
return
}
} else if cmdArgs.existsArg("c", "clean") {
err = cleanDependencies()
} else if len(cmdArgs.targets) > 0 {

View file

@ -43,10 +43,20 @@ type Configuration struct {
var version = "3.373"
// configFileName holds the name of the config file.
const configFileName string = "config.json"
// vcsFileName holds the name of the vcs file.
const vcsFileName string = "vcs.json"
// completionFilePrefix holds the prefix used for storing shell completion files.
const completionFilePrefix string = "aur_"
// baseURL givers the AUR default address.
const baseURL string = "https://aur.archlinux.org"
var savedInfo infos
// savedInfo holds the current vcs info
var savedInfo vcsInfo
// configfile holds yay config file path.
var configFile string
@ -54,7 +64,7 @@ var configFile string
// vcsfile holds yay vcs info file path.
var vcsFile string
//completion file
// completion file
var completionFile string
// changedConfig holds whether or not the config has changed

View file

@ -339,20 +339,6 @@ func askEditPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error {
return nil
}
func updateVSCdb(pkgs []*rpc.Pkg, pkgbuild *gopkg.PKGBUILD) {
for _, pkgsource := range pkgbuild.Source {
owner, repo := parseSource(pkgsource)
if owner != "" && repo != "" {
for _, pkg := range pkgs {
err := branchInfo(pkg.Name, owner, repo)
if err != nil {
fmt.Println(err)
}
}
}
}
}
func parsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) error {
for k, pkg := range pkgs {
dir := config.BuildDir + pkg.PackageBase + "/"
@ -366,7 +352,11 @@ func parsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bas
}
srcinfos[pkg.PackageBase] = pkgbuild
updateVSCdb(bases[pkg.PackageBase], pkgbuild)
for _, pkg := range bases[pkg.PackageBase] {
updateVCSData(pkg.Name, pkgbuild.Source)
}
}
return nil
@ -493,7 +483,10 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD,
return err
}
updateVSCdb(bases[pkg.PackageBase], srcinfo)
for _, pkg := range bases[pkg.PackageBase] {
updateVCSData(pkg.Name, srcinfo.Source)
}
if len(depArguments.targets) > 0 {
_, stderr, err := passToPacmanCapture(depArguments)
if err != nil {

View file

@ -144,12 +144,12 @@ loop:
}
func upDevel(remote []alpm.Package, packageC chan upgrade, done chan bool) {
for _, e := range savedInfo {
for vcsName, e := range savedInfo {
if e.needsUpdate() {
found := false
var pkg alpm.Package
for _, r := range remote {
if r.Name() == e.Package {
if r.Name() == vcsName {
found = true
pkg = r
}
@ -159,10 +159,10 @@ func upDevel(remote []alpm.Package, packageC chan upgrade, done chan bool) {
fmt.Print(magenta("Warning: "))
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", cyan(pkg.Name()), pkg.Version(), "git")
} else {
packageC <- upgrade{e.Package, "devel", pkg.Version(), "commit-" + e.SHA[0:6]}
packageC <- upgrade{pkg.Name(), "devel", pkg.Version(), "latest-commit"}
}
} else {
removeVCSPackage([]string{e.Package})
removeVCSPackage([]string{vcsName})
}
}
}

236
vcs.go
View file

@ -1,38 +1,21 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
)
// branch contains the information of a repository branch
type branch struct {
Name string `json:"name"`
Commit struct {
SHA string `json:"sha"`
} `json:"commit"`
}
type branches []branch
// Info contains the last commit sha of a repo
type Info struct {
Package string `json:"pkgname"`
URL string `json:"url"`
SHA string `json:"sha"`
}
type infos []Info
// Repo contains information about the repository
type repo struct {
Name string `json:"name"`
FullName string `json:"full_name"`
DefaultBranch string `json:"default_branch"`
type vcsInfo map[string]shaInfos
type shaInfos map[string]shaInfo
type shaInfo struct {
Protocols []string `json:"protocols"`
Brach string `json:"branch"`
SHA string `json:"sha"`
}
// createDevelDB forces yay to create a DB of the existing development packages
@ -50,128 +33,127 @@ func createDevelDB() error {
return err
}
// parseSource returns owner and repo from source
func parseSource(source string) (owner string, repo string) {
// parseSource returns the git url, default branch and protocols it supports
func parseSource(source string) (url string, branch string, protocols []string) {
if !(strings.Contains(source, "git://") ||
strings.Contains(source, ".git") ||
strings.Contains(source, "git+https://")) {
return
return "", "", nil
}
split := strings.Split(source, "github.com/")
if len(split) > 1 {
secondSplit := strings.Split(split[1], "/")
if len(secondSplit) > 1 {
owner = secondSplit[0]
thirdSplit := strings.Split(secondSplit[1], ".git")
if len(thirdSplit) > 0 {
repo = thirdSplit[0]
}
split := strings.Split(source, "::")
source = split[len(split)-1]
split = strings.SplitN(source, "://", 2)
if len(split) != 2 {
return "", "", nil
}
protocols = strings.Split(split[0], "+")
split = strings.SplitN(split[1], "#", 2)
if len(split) == 2 {
secondSplit := strings.SplitN(split[1], "=", 2)
if secondSplit[0] != "branch" {
//source has #commit= or #tag= which makes them not vcs
//packages because they reference a specific point
return "", "", nil
}
if len(secondSplit) == 2 {
url = split[0]
branch = secondSplit[1]
}
} else {
url = split[0]
branch = "HEAD"
}
return
}
func (info *Info) needsUpdate() bool {
var newRepo repo
var newBranches branches
if strings.HasSuffix(info.URL, "/branches") {
info.URL = info.URL[:len(info.URL)-9]
}
infoResp, infoErr := http.Get(info.URL)
if infoErr != nil {
fmt.Println(infoErr)
return false
}
defer infoResp.Body.Close()
infoBody, _ := ioutil.ReadAll(infoResp.Body)
var err = json.Unmarshal(infoBody, &newRepo)
if err != nil {
fmt.Printf("Cannot update '%v'\nError: %v\nStatus code: %v\nBody: %v\n",
info.Package, err, infoResp.StatusCode, string(infoBody))
return false
func updateVCSData(pkgName string, sources []string) {
if savedInfo == nil {
savedInfo = make(vcsInfo)
}
defaultBranch := newRepo.DefaultBranch
branchesURL := info.URL + "/branches"
info := make(shaInfos)
branchResp, branchErr := http.Get(branchesURL)
if branchErr != nil {
fmt.Println(branchErr)
return false
for _, source := range sources {
url, branch, protocols := parseSource(source)
if url == "" || branch == "" {
continue
}
commit := getCommit(url, branch, protocols)
if commit == "" {
continue
}
info[url] = shaInfo{
protocols,
branch,
commit,
}
savedInfo[pkgName] = info
saveVCSInfo()
}
defer branchResp.Body.Close()
}
branchBody, _ := ioutil.ReadAll(branchResp.Body)
err = json.Unmarshal(branchBody, &newBranches)
if err != nil {
fmt.Printf("Cannot update '%v'\nError: %v\nStatus code: %v\nBody: %v\n",
info.Package, err, branchResp.StatusCode, string(branchBody))
return false
func getCommit(url string, branch string, protocols []string) string {
for _, protocol := range protocols {
var outbuf bytes.Buffer
cmd := exec.Command("git", "ls-remote", protocol+"://"+url, branch)
cmd.Stdout = &outbuf
err := cmd.Start()
if err != nil {
continue
}
//for some reason
//git://bitbucket.org/volumesoffun/polyvox.git` hangs on my
//machine but using http:// instead of git does not hang.
//Introduce a time out so this can not hang
timer := time.AfterFunc(5*time.Second, func() {
cmd.Process.Kill()
})
err = cmd.Wait()
timer.Stop()
if err != nil {
continue
}
err = cmd.Run()
stdout := outbuf.String()
split := strings.Fields(stdout)
if len(split) < 2 {
continue
}
commit := split[0]
return commit
}
for _, e := range newBranches {
if e.Name == defaultBranch {
return e.Commit.SHA != info.SHA
return ""
}
func (infos shaInfos) needsUpdate() bool {
for url, info := range infos {
hash := getCommit(url, info.Brach, info.Protocols)
if hash != info.SHA {
return true
}
}
return false
}
func inStore(pkgName string) *Info {
for i, e := range savedInfo {
if pkgName == e.Package {
return &savedInfo[i]
}
}
return nil
}
// branchInfo updates saved information
func branchInfo(pkgName string, owner string, repoName string) (err error) {
updated := false
var newRepo repo
var newBranches branches
url := "https://api.github.com/repos/" + owner + "/" + repoName
repoResp, err := http.Get(url)
if err != nil {
return
}
defer repoResp.Body.Close()
_ = json.NewDecoder(repoResp.Body).Decode(&newRepo)
defaultBranch := newRepo.DefaultBranch
branchesURL := url + "/branches"
branchResp, err := http.Get(branchesURL)
if err != nil {
return
}
defer branchResp.Body.Close()
_ = json.NewDecoder(branchResp.Body).Decode(&newBranches)
packinfo := inStore(pkgName)
for _, e := range newBranches {
if e.Name == defaultBranch {
updated = true
if packinfo != nil {
packinfo.Package = pkgName
packinfo.URL = url
packinfo.SHA = e.Commit.SHA
} else {
savedInfo = append(savedInfo, Info{Package: pkgName, URL: url, SHA: e.Commit.SHA})
}
}
}
if updated {
saveVCSInfo()
}
return
func inStore(pkgName string) shaInfos {
return savedInfo[pkgName]
}
func saveVCSInfo() error {

View file

@ -4,29 +4,64 @@ import (
"testing"
)
func isEqual(a, b []string) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestParsing(t *testing.T) {
type source struct {
sourceurl string
owner string
repo string
URL string
Branch string
Protocols []string
}
neovim := source{sourceurl: "git+https://github.com/neovim/neovim.git"}
neovim.owner, neovim.repo = parseSource(neovim.sourceurl)
if neovim.owner != "neovim" || neovim.repo != "neovim" {
t.Fatalf("Expected to find neovim/neovim, found %+v/%+v", neovim.owner, neovim.repo)
urls := []string{
"git+https://github.com/neovim/neovim.git",
"git://github.com/jguer/yay.git#branch=master",
"git://github.com/davidgiven/ack",
"git://github.com/jguer/yay.git#tag=v3.440",
"git://github.com/jguer/yay.git#commit=e5470c88c6e2f9e0f97deb4728659ffa70ef5d0c",
"a+b+c+d+e+f://github.com/jguer/yay.git#branch=foo",
}
yay := source{sourceurl: "git://github.com/jguer/yay.git#branch=master"}
yay.owner, yay.repo = parseSource(yay.sourceurl)
if yay.owner != "jguer" || yay.repo != "yay" {
t.Fatalf("Expected to find jguer/yay, found %+v/%+v", yay.owner, yay.repo)
sources := []source{
{"github.com/neovim/neovim.git", "HEAD", []string{"git", "https"}},
{"github.com/jguer/yay.git", "master", []string{"git"}},
{"github.com/davidgiven/ack", "HEAD", []string{"git"}},
{"", "", nil},
{"", "", nil},
{"github.com/jguer/yay.git", "foo", []string{"a", "b", "c", "d", "e", "f"}},
}
ack := source{sourceurl: "git://github.com/davidgiven/ack"}
ack.owner, ack.repo = parseSource(ack.sourceurl)
if ack.owner != "davidgiven" || ack.repo != "ack" {
t.Fatalf("Expected to find davidgiven/ack, found %+v/%+v", ack.owner, ack.repo)
for n, url := range urls {
url, branch, protocols := parseSource(url)
compare := sources[n]
if url != compare.URL ||
branch != compare.Branch ||
!isEqual(protocols, compare.Protocols) {
t.Fatalf("Expected url=%+v branch=%+v protocols=%+v\ngot url=%+v branch=%+v protocols=%+v", url, branch, protocols, compare.URL, compare.Branch, compare.Protocols)
}
}
}