-
Notifications
You must be signed in to change notification settings - Fork 8
add read only yum support (yum search, yum info) #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1298c05
22a3705
524f603
d711045
c2716bf
6a96bf6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,149 @@ | ||||||||||||||||||||||||||
| // Package yum provides a package manager implementation for RedHat-based systems using | ||||||||||||||||||||||||||
| // YUM as the underlying package management tool. | ||||||||||||||||||||||||||
| package yum | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||
| "regexp" | ||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| "github.com/bluet/syspkg/manager" | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // ParseFindOutput parses the output of `yum search packageName` command | ||||||||||||||||||||||||||
| // and returns a list of available packages that match the search query. It extracts package | ||||||||||||||||||||||||||
| // information such as name, architecture from the | ||||||||||||||||||||||||||
| // output, and stores them in a list of manager.PackageInfo objects. | ||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||
| // The output format is expected to be similar to the following example: | ||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||
| //Last metadata expiration check: 0:26:09 ago on Thu 22 May 2025 04:30:18 PM UTC. | ||||||||||||||||||||||||||
| // ==================================================Name Exactly Matched: nginx ==================================================== | ||||||||||||||||||||||||||
| //nginx.x86_64 : A high performance web server and reverse proxy server | ||||||||||||||||||||||||||
| //====================================================Name & Summary Matched: nginx================================================== | ||||||||||||||||||||||||||
| //nginx-all-modules.noarch : A meta package that installs all available Nginx modules | ||||||||||||||||||||||||||
| //nginx-core.x86_64 : nginx minimal core | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // The function first removes the "Last Metadata..." and the "=========" | ||||||||||||||||||||||||||
| // lines, and then processes each package entry line to extract relevant | ||||||||||||||||||||||||||
| // information. | ||||||||||||||||||||||||||
| func ParseFindOutput(msg string, opts *manager.Options) []manager.PackageInfo { | ||||||||||||||||||||||||||
| var packages []manager.PackageInfo | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // remove the last empty line | ||||||||||||||||||||||||||
| msg = strings.TrimSuffix(msg, "\n") | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // split output by empty lines | ||||||||||||||||||||||||||
| var lines []string = strings.Split(msg, "\n") | ||||||||||||||||||||||||||
| var packageLineRegex = regexp.MustCompile(`^[\w\d-]+\.[\w\d_]+`) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| for _, line := range lines { | ||||||||||||||||||||||||||
| if strings.HasPrefix(line, "=======") { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if strings.HasPrefix(line, "Last metadata") { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if packageLineRegex.MatchString(line) { | ||||||||||||||||||||||||||
| parts := strings.Fields(line) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // if name is empty, it might be not what we want | ||||||||||||||||||||||||||
| if parts[0] == "" { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| name_arch := strings.Split(parts[0], ".") | ||||||||||||||||||||||||||
| if len(name_arch) != 2 { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| packageInfo := manager.PackageInfo{ | ||||||||||||||||||||||||||
| Name: name_arch[0], | ||||||||||||||||||||||||||
| Arch: name_arch[1], | ||||||||||||||||||||||||||
| PackageManager: pm, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| packages = append(packages, packageInfo) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return packages | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // ParseListInstalledOutput parses the output of `yum list --installed` command | ||||||||||||||||||||||||||
| // and returns a list of installed packages. It extracts the package name, version, | ||||||||||||||||||||||||||
| // and architecture from the output and stores them in a list of manager.PackageInfo objects. | ||||||||||||||||||||||||||
| func ParseListInstalledOutput(msg string, opts *manager.Options) []manager.PackageInfo { | ||||||||||||||||||||||||||
| var packages []manager.PackageInfo | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // remove the last empty line | ||||||||||||||||||||||||||
| msg = strings.TrimSuffix(msg, "\n") | ||||||||||||||||||||||||||
| lines := strings.Split(string(msg), "\n") | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| for _, line := range lines { | ||||||||||||||||||||||||||
| if strings.HasPrefix(line, "Installed Packages") { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if len(line) > 0 { | ||||||||||||||||||||||||||
| parts := strings.Fields(line) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // if it doesn't split correctly, or the name is empty, it might be not what we want | ||||||||||||||||||||||||||
| if len(parts) < 2 || parts[0] == "" { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| name_arch := strings.Split(parts[0], ".") | ||||||||||||||||||||||||||
| if len(name_arch) != 2 { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| name := name_arch[0] | ||||||||||||||||||||||||||
| arch := name_arch[1] | ||||||||||||||||||||||||||
|
Comment on lines
+93
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix variable naming convention. Variable - name_arch := strings.Split(parts[0], ".")
- if len(name_arch) != 2 {
+ nameArch := strings.Split(parts[0], ".")
+ if len(nameArch) != 2 {
continue
}
- name := name_arch[0]
- arch := name_arch[1]
+ name := nameArch[0]
+ arch := nameArch[1]📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| packageInfo := manager.PackageInfo{ | ||||||||||||||||||||||||||
| Name: name, | ||||||||||||||||||||||||||
| Version: parts[1], | ||||||||||||||||||||||||||
| Status: manager.PackageStatusInstalled, | ||||||||||||||||||||||||||
|
aijanai marked this conversation as resolved.
|
||||||||||||||||||||||||||
| Arch: arch, | ||||||||||||||||||||||||||
| PackageManager: "yum", | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| packages = append(packages, packageInfo) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return packages | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // ParsePackageInfoOutput parses the output of `yum info packageName` command | ||||||||||||||||||||||||||
| // and returns a manager.PackageInfo object containing package information such as name, version, | ||||||||||||||||||||||||||
| // architecture, and category. This function is useful for getting detailed package information. | ||||||||||||||||||||||||||
| func ParsePackageInfoOutput(msg string, opts *manager.Options) manager.PackageInfo { | ||||||||||||||||||||||||||
| var pkg manager.PackageInfo | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // remove the last empty line | ||||||||||||||||||||||||||
| msg = strings.TrimSuffix(msg, "\n") | ||||||||||||||||||||||||||
| lines := strings.Split(string(msg), "\n") | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| for _, line := range lines { | ||||||||||||||||||||||||||
| if len(line) > 0 { | ||||||||||||||||||||||||||
| parts := strings.SplitN(line, ":", 2) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if len(parts) != 2 { | ||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| key := strings.TrimSpace(parts[0]) | ||||||||||||||||||||||||||
| value := strings.TrimSpace(parts[1]) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| switch key { | ||||||||||||||||||||||||||
| case "Name": | ||||||||||||||||||||||||||
| pkg.Name = value | ||||||||||||||||||||||||||
| case "Version": | ||||||||||||||||||||||||||
| pkg.Version = value | ||||||||||||||||||||||||||
| case "Architecture": | ||||||||||||||||||||||||||
| pkg.Arch = value | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| pkg.PackageManager = "yum" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return pkg | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| // Package yum provides an implementation of the syspkg manager interface for the yum package manager. | ||
| // It provides an Go (golang) API interface for interacting with the YUM package manager. | ||
| // This package is a wrapper around the yum command line tool. | ||
| // | ||
| // YUM was the default package manager on RedHat-based systems such as Centos, it has been recently superseded by DNF (Dandified YUM) | ||
| // | ||
| // This package is part of the syspkg library. | ||
| package yum | ||
|
|
||
| import ( | ||
| "errors" | ||
| "log" | ||
| "os" | ||
| "os/exec" | ||
|
|
||
| "github.com/bluet/syspkg/manager" | ||
| ) | ||
|
|
||
| var pm string = "yum" | ||
|
|
||
| // Constants used for yum commands | ||
| const ( | ||
| ArgsAssumeYes string = "-y" | ||
| ArgsAssumeNo string = "--assumeno" | ||
| ArgsQuiet string = "-q" | ||
| ArgsDryRun string = "" | ||
| ArgsFixBroken string = "" | ||
| ArgsPurge string = "" | ||
| ArgsAutoRemove string = "" | ||
| ArgsShowProgress string = "" | ||
| ) | ||
|
|
||
| // PackageManager implements the manager.PackageManager interface for the yum package manager. | ||
| type PackageManager struct{} | ||
|
|
||
| // IsAvailable checks if the yum package manager is available on the system. | ||
| func (a *PackageManager) IsAvailable() bool { | ||
| _, err := exec.LookPath(pm) | ||
| return err == nil | ||
| } | ||
|
|
||
| // GetPackageManager returns the name of the yum package manager. | ||
| func (a *PackageManager) GetPackageManager() string { | ||
| return pm | ||
| } | ||
|
|
||
| func (a *PackageManager) Install(pkgs []string, opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
|
|
||
| func (a *PackageManager) Delete(pkgs []string, opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
|
|
||
| // Refresh updates the package list using the yum package manager. | ||
| func (a *PackageManager) Refresh(opts *manager.Options) error { | ||
| cmd := exec.Command(pm, "clean", "expire-cache") | ||
|
|
||
| if opts == nil { | ||
| opts = &manager.Options{ | ||
| DryRun: false, | ||
| Interactive: false, | ||
| Verbose: false, | ||
| } | ||
| } | ||
| if opts.Interactive { | ||
| cmd.Stdout = os.Stdout | ||
| cmd.Stderr = os.Stderr | ||
| cmd.Stdin = os.Stdin | ||
| err := cmd.Run() | ||
| return err | ||
| } else { | ||
| out, err := cmd.Output() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if opts.Verbose { | ||
| log.Println(string(out)) | ||
| } | ||
| return nil | ||
| } | ||
| } | ||
|
|
||
| // Find searches for packages matching the provided keywords using the yum package manager. | ||
| func (a *PackageManager) Find(keywords []string, opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| args := append([]string{"search"}, keywords...) | ||
| cmd := exec.Command(pm, args...) | ||
|
|
||
| out, err := cmd.Output() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return ParseFindOutput(string(out), opts), nil | ||
| } | ||
|
|
||
| // ListInstalled lists all installed packages using the yum package manager. | ||
| func (a *PackageManager) ListInstalled(opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| args := []string{"list", "--installed"} | ||
| cmd := exec.Command(pm, args...) | ||
| out, err := cmd.Output() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return ParseListInstalledOutput(string(out), opts), nil | ||
| } | ||
|
|
||
| func (a *PackageManager) ListUpgradable(opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
| func (a *PackageManager) Upgrade(pkgs []string, opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
| func (a *PackageManager) UpgradeAll(opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
| func (a *PackageManager) Clean(opts *manager.Options) error { | ||
| return a.Refresh(nil) | ||
|
aijanai marked this conversation as resolved.
|
||
| } | ||
|
aijanai marked this conversation as resolved.
|
||
|
|
||
| // GetPackageInfo retrieves package information for the specified package using the yum package manager. | ||
| func (a *PackageManager) GetPackageInfo(pkg string, opts *manager.Options) (manager.PackageInfo, error) { | ||
| cmd := exec.Command(pm, "info", pkg) | ||
| out, err := cmd.Output() | ||
| if err != nil { | ||
| return manager.PackageInfo{}, err | ||
| } | ||
| return ParsePackageInfoOutput(string(out), opts), nil | ||
| } | ||
|
|
||
| func (a *PackageManager) AutoRemove(opts *manager.Options) ([]manager.PackageInfo, error) { | ||
| return nil, errors.New("not implemented") | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.