added github source search functionality

This commit is contained in:
e 2025-01-21 18:48:58 -05:00
parent 3fb40239fa
commit 85250a1b96
6 changed files with 141 additions and 11 deletions

View File

@ -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 <package1[@version]> [package2[@version]...] - Install packages
remove <package1> [package2...] - Remove packages
search <term> - Search for packages
source <term> - 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

8
go.mod
View File

@ -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
)

12
go.sum
View File

@ -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=

12
main.go
View File

@ -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()

60
pkg_manager/github.go Normal file
View File

@ -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
}

View File

@ -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
}