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:\ Search for packages:\
```upm search nginx``` ```upm search nginx```
Search for source code:\
```upm source nginx``` # Search GitHub for source code repositories
Update package lists:\ Update package lists:\
```upm update``` ```upm update```
@ -115,6 +118,13 @@ Install using snap:\
Install using flatpak:\ Install using flatpak:\
```upm -u flatpak install org.mozilla.firefox``` ```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 ## Project Structure
``` ```
upm-universalpackagemanager/ upm-universalpackagemanager/
@ -146,3 +156,16 @@ Supernets, PP4L, DigitalGangster
## Support ## Support
If you encounter any issues or have questions, please file an issue on the git.supernets.org repository. 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 go 1.22
require ( require (
github.com/briandowns/spinner v1.23.0 github.com/briandowns/spinner v1.23.2
github.com/fatih/color v1.16.0 github.com/fatih/color v1.18.0
) )
require ( require (
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // 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 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.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2FW8w=
github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 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 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 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= 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= 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.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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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/fatih/color"
"github.com/briandowns/spinner" "github.com/briandowns/spinner"
"git.supernets.org/e/managerofmanagers/pkg_manager" "upm/pkg_manager"
) )
var ( var (
@ -274,6 +274,16 @@ func handleCommand(pm *pkg_manager.Manager, args []string) {
os.Exit(1) 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: default:
fmt.Fprintf(os.Stderr, "Unknown command: %s\n", command) fmt.Fprintf(os.Stderr, "Unknown command: %s\n", command)
printUsage() 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"
"os/exec" "os/exec"
"strings" "strings"
"time"
"github.com/briandowns/spinner"
) )
// PackageManager interface defines common operations // PackageManager interface defines common operations
@ -24,6 +27,7 @@ type PackageManager interface {
AutoRemove() error AutoRemove() error
CheckDependencies(pkg string) error CheckDependencies(pkg string) error
ShowDependencies(pkg string) error ShowDependencies(pkg string) error
HandleSource(appName string) error
} }
// Manager represents a concrete package manager // Manager represents a concrete package manager
@ -423,4 +427,37 @@ func DetectPackageManager() (*Manager, error) {
// NeedsSudo returns whether this package manager needs sudo // NeedsSudo returns whether this package manager needs sudo
func (m *Manager) NeedsSudo() bool { func (m *Manager) NeedsSudo() bool {
return m.needsSudo && os.Geteuid() != 0 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
} }