mirror of
https://github.com/Jguer/yay
synced 2024-09-14 13:51:12 +00:00
Merge pull request #206 from Morganamilo/lsremote
Use git ls-remote to track devel updates
This commit is contained in:
commit
251d31c970
15
clean.go
15
clean.go
|
@ -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
10
cmd.go
|
@ -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 {
|
||||
|
|
14
config.go
14
config.go
|
@ -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
|
||||
|
|
25
install.go
25
install.go
|
@ -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 {
|
||||
|
|
|
@ -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
236
vcs.go
|
@ -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 {
|
||||
|
|
67
vcs_test.go
67
vcs_test.go
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue