From 85250a1b96810f3be4fb4195273c8eb5a22dface Mon Sep 17 00:00:00 2001 From: e Date: Tue, 21 Jan 2025 18:48:58 -0500 Subject: [PATCH] added github source search functionality --- README.md | 23 +++++++++++++++ go.mod | 8 ++--- go.sum | 12 ++++---- main.go | 12 +++++++- pkg_manager/github.go | 60 ++++++++++++++++++++++++++++++++++++++ pkg_manager/pkg_manager.go | 37 +++++++++++++++++++++++ 6 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 pkg_manager/github.go diff --git a/README.md b/README.md index 2b068a0..1bca887 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,9 @@ Remove packages:\ Search for packages:\ ```upm search nginx``` +Search for source code:\ + ```upm source nginx``` # Search GitHub for source code repositories + Update package lists:\ ```upm update``` @@ -115,6 +118,13 @@ Install using snap:\ Install using flatpak:\ ```upm -u flatpak install org.mozilla.firefox``` +### Source Code Search + +Search for source code repositories: +`upm source nginx` + +This command searches GitHub for source code repositories related to the specified package. + ## Project Structure ``` upm-universalpackagemanager/ @@ -146,3 +156,16 @@ Supernets, PP4L, DigitalGangster ## Support If you encounter any issues or have questions, please file an issue on the git.supernets.org repository. + +Commands: + install [package2[@version]...] - Install packages + remove [package2...] - Remove packages + search - Search for packages + source - Search GitHub for source code + +Examples: + upm install nginx@1.18.0 + upm -u snap install firefox + upm repo add https://repo.example.com + upm show-deps nginx + upm source nginx # Find source code repositories \ No newline at end of file diff --git a/go.mod b/go.mod index ddf6b49..9f93c76 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ -module git.supernets.org/e/managerofmanagers +module upm go 1.22 require ( - github.com/briandowns/spinner v1.23.0 - github.com/fatih/color v1.16.0 + github.com/briandowns/spinner v1.23.2 + github.com/fatih/color v1.18.0 ) require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index fb4411b..d064337 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= -github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/briandowns/spinner v1.23.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2FW8w= +github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -9,7 +9,7 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/main.go b/main.go index c439d61..9e61d58 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/fatih/color" "github.com/briandowns/spinner" - "git.supernets.org/e/managerofmanagers/pkg_manager" + "upm/pkg_manager" ) var ( @@ -274,6 +274,16 @@ func handleCommand(pm *pkg_manager.Manager, args []string) { os.Exit(1) } + case "source": + if len(cmdArgs) == 0 { + fmt.Fprintln(os.Stderr, "Error: package name required") + os.Exit(1) + } + if err := pm.HandleSource(cmdArgs[0]); err != nil { + fmt.Fprintf(os.Stderr, "Failed to search source: %v\n", err) + os.Exit(1) + } + default: fmt.Fprintf(os.Stderr, "Unknown command: %s\n", command) printUsage() diff --git a/pkg_manager/github.go b/pkg_manager/github.go new file mode 100644 index 0000000..6012b68 --- /dev/null +++ b/pkg_manager/github.go @@ -0,0 +1,60 @@ +package pkg_manager + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "time" +) + +type GitHubRepo struct { + FullName string `json:"full_name"` + Description string `json:"description"` + HTMLURL string `json:"html_url"` + Stars int `json:"stargazers_count"` + Language string `json:"language"` +} + +type GitHubSearchResponse struct { + TotalCount int `json:"total_count"` + Items []GitHubRepo `json:"items"` +} + +func SearchGitHubSource(query string) ([]GitHubRepo, error) { + baseURL := "https://api.github.com/search/repositories" + + // Create search query + params := url.Values{} + params.Add("q", query) + params.Add("sort", "stars") + params.Add("order", "desc") + params.Add("per_page", "5") // Limit to top 5 results + + client := &http.Client{Timeout: 10 * time.Second} + + req, err := http.NewRequest("GET", baseURL+"?"+params.Encode(), nil) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + req.Header.Set("Accept", "application/vnd.github.v3+json") + req.Header.Set("User-Agent", "UPM-Package-Manager") + + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("error making request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("GitHub API returned status: %d", resp.StatusCode) + } + + var searchResp GitHubSearchResponse + if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil { + return nil, fmt.Errorf("error decoding response: %w", err) + } + + return searchResp.Items, nil +} \ No newline at end of file diff --git a/pkg_manager/pkg_manager.go b/pkg_manager/pkg_manager.go index fa4bf17..6da967d 100644 --- a/pkg_manager/pkg_manager.go +++ b/pkg_manager/pkg_manager.go @@ -6,6 +6,9 @@ import ( "os" "os/exec" "strings" + "time" + + "github.com/briandowns/spinner" ) // PackageManager interface defines common operations @@ -24,6 +27,7 @@ type PackageManager interface { AutoRemove() error CheckDependencies(pkg string) error ShowDependencies(pkg string) error + HandleSource(appName string) error } // Manager represents a concrete package manager @@ -423,4 +427,37 @@ func DetectPackageManager() (*Manager, error) { // NeedsSudo returns whether this package manager needs sudo func (m *Manager) NeedsSudo() bool { return m.needsSudo && os.Geteuid() != 0 +} + +func (m *Manager) HandleSource(appName string) error { + fmt.Printf("Searching source code for %s...\n", appName) + + s := spinner.New(spinner.CharSets[9], 100*time.Millisecond) + s.Start() + + repos, err := SearchGitHubSource(appName) + s.Stop() + + if err != nil { + return fmt.Errorf("error searching GitHub: %w", err) + } + + if len(repos) == 0 { + fmt.Printf("No source code repositories found for '%s'\n", appName) + return nil + } + + fmt.Printf("\nFound %d source code repositories:\n\n", len(repos)) + + for i, repo := range repos { + fmt.Printf("%d. %s\n", i+1, repo.FullName) + if repo.Description != "" { + fmt.Printf(" Description: %s\n", repo.Description) + } + fmt.Printf(" Language: %s\n", repo.Language) + fmt.Printf(" Stars: %d\n", repo.Stars) + fmt.Printf(" URL: %s\n\n", repo.HTMLURL) + } + + return nil } \ No newline at end of file