From 01b7d2b21bbcb428bfe6f15088926b493ad8e803 Mon Sep 17 00:00:00 2001 From: M0Rf30 Date: Sun, 29 Oct 2023 16:27:11 +0100 Subject: [PATCH] documentation: add more documentation --- .editorconfig | 2 +- pkg/apk/apk.go | 31 ++++++++++++++- pkg/builder/builder.go | 4 +- pkg/builder/utils.go | 4 ++ pkg/constants/constants.go | 9 +++++ pkg/debian/debian.go | 65 ++++++++++++++++++++++++++++++++ pkg/packer/packer.go | 8 ++-- pkg/pacman/pacman.go | 28 ++++++++++++++ pkg/parser/parser.go | 26 +++++++++++++ pkg/pkgbuild/pkgbuild.go | 8 ++-- pkg/project/project.go | 73 +++++++++++++++++++++++++++++++++++- pkg/redhat/redhat.go | 70 ++++++++++++++++++++++++++++++---- pkg/set/set.go | 23 +++++++++++- pkg/source/source.go | 77 +++++++++++++++++++++++++++++++++----- pkg/utils/file.go | 54 +++++++++++++++++++++++++- pkg/utils/proc.go | 16 ++++++++ pkg/utils/strings.go | 23 +++++++----- pkg/utils/utils.go | 41 +++++++++++++++----- 18 files changed, 508 insertions(+), 54 deletions(-) diff --git a/.editorconfig b/.editorconfig index af262f4..68d1490 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,4 +11,4 @@ indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = false \ No newline at end of file +insert_final_newline = true \ No newline at end of file diff --git a/pkg/apk/apk.go b/pkg/apk/apk.go index 5132dd4..211388d 100644 --- a/pkg/apk/apk.go +++ b/pkg/apk/apk.go @@ -7,11 +7,21 @@ import ( "github.com/M0Rf30/yap/pkg/utils" ) +// Apk represents the APK package manager. +// +// It contains the directory path of the package and the PKGBUILD struct, which +// contains the metadata and build instructions for the package. type Apk struct { + // PKGBUILD is a pointer to the pkgbuild.PKGBUILD struct, which contains information about the package being built. PKGBUILD *pkgbuild.PKGBUILD - apkDir string + + // apkDir is a string representing the directory where the APK package files are stored. + apkDir string } +// Build builds the APK package. +// +// It takes the artifactsPath as a parameter and returns an error. func (a *Apk) Build(artifactsPath string) error { a.apkDir = filepath.Join(a.PKGBUILD.StartDir, "apk") @@ -43,6 +53,10 @@ func (a *Apk) Build(artifactsPath string) error { return err } +// Install installs the APK package to the specified artifacts path. +// +// It takes a string parameter `artifactsPath` which specifies the path where the artifacts are located. +// It returns an error if there was an error during the installation process. func (a *Apk) Install(artifactsPath string) error { var err error @@ -69,6 +83,10 @@ func (a *Apk) Install(artifactsPath string) error { return err } +// Prepare prepares the Apk by adding dependencies to the PKGBUILD file. +// +// makeDepends is a slice of strings representing the dependencies to be added. +// It returns an error if there is any issue with adding the dependencies. func (a *Apk) Prepare(makeDepends []string) error { args := []string{ "add", @@ -82,6 +100,9 @@ func (a *Apk) Prepare(makeDepends []string) error { return err } +// PrepareEnvironment prepares the build environment for APK packaging. +// It installs requested Go tools if 'golang' is true. +// It returns an error if any step fails. func (a *Apk) PrepareEnvironment(golang bool) error { var err error @@ -104,6 +125,8 @@ func (a *Apk) PrepareEnvironment(golang bool) error { return err } +// Update updates the APK package manager's package database. +// It returns an error if the update process fails. func (a *Apk) Update() error { err := a.PKGBUILD.GetUpdates("apk", "update") if err != nil { @@ -113,6 +136,8 @@ func (a *Apk) Update() error { return err } +// apkBuild compiles the APK package using 'abuild-keygen' and 'abuild'. +// It returns an error if any compilation step fails. func (a *Apk) apkBuild(artifactsPath string) error { err := utils.Exec(a.apkDir, "abuild-keygen", @@ -135,6 +160,10 @@ func (a *Apk) apkBuild(artifactsPath string) error { return err } +// makePackerDir creates the necessary directories for the Apk struct. +// +// It does not take any parameters. +// It returns an error if any of the directory operations fail. func (a *Apk) makePackerDir() error { err := utils.ExistsMakeDir(a.apkDir) if err != nil { diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index 0323d04..657c5b4 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -66,8 +66,8 @@ func (builder *Builder) Package() error { return err } -// build executes the instructions provided by a single project build() -// function. It returns any error if occurred. +// build executes a set of instructions provided by a project build function. If +// there is an error during execution, it returns the error. func (builder *Builder) build() error { err := RunScript(builder.PKGBUILD.Build) if err != nil { diff --git a/pkg/builder/utils.go b/pkg/builder/utils.go index e14fc0f..42d3622 100644 --- a/pkg/builder/utils.go +++ b/pkg/builder/utils.go @@ -10,6 +10,10 @@ import ( "mvdan.cc/sh/v3/syntax" ) +// RunScript runs a shell script. +// +// It takes a string parameter `cmds` which represents the shell script to be executed. +// The function returns an error if there was an issue running the script. func RunScript(cmds string) error { script, _ := syntax.NewParser().Parse(strings.NewReader(cmds), "") diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 8bb7c94..348c694 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -55,6 +55,15 @@ var ( CleanPrevious = false ) +// init initializes the package. +// +// It iterates over the Releases slice and adds each release to the ReleasesSet set. +// It also extracts the distribution name from each release and adds it to the Distros slice. +// The function then iterates over the Distros slice and assigns the corresponding package manager +// to each distribution in the DistroPackageManager map. +// If a distribution does not have a supported package manager, the function prints an error message +// and exits the program. +// Finally, it adds each package manager to the PackagersSet set. func init() { var packageManager string diff --git a/pkg/debian/debian.go b/pkg/debian/debian.go index 8de5834..936e1db 100644 --- a/pkg/debian/debian.go +++ b/pkg/debian/debian.go @@ -16,17 +16,32 @@ import ( "github.com/otiai10/copy" ) +// Debian represents a Debian package. +// +// It contains the directory path of the package and the PKGBUILD struct, which +// contains the metadata and build instructions for the package. type Debian struct { debDir string PKGBUILD *pkgbuild.PKGBUILD } +// getArch updates the architecture field in the Debian struct. +// +// It iterates over the architecture values in the PKGBUILD field of the Debian struct +// and replaces them with the corresponding values from the DebianArchs map. func (d *Debian) getArch() { for index, arch := range d.PKGBUILD.Arch { d.PKGBUILD.Arch[index] = DebianArchs[arch] } } +// createConfFiles creates the conffiles file in the Debian package. +// +// It iterates over the Backup field of the PKGBUILD struct and adds each name +// to the data string. The data string is then written to the conffiles file +// located at the debDir path. +// +// Returns an error if there was a problem creating or writing to the file. func (d *Debian) createConfFiles() error { var err error if len(d.PKGBUILD.Backup) == 0 { @@ -53,6 +68,10 @@ func (d *Debian) createConfFiles() error { return err } +// createDebconfTemplate creates a Debian package configuration file template. +// +// It does not take any parameters. +// It returns an error if there was an issue creating the template. func (d *Debian) createDebconfTemplate() error { var err error if d.PKGBUILD.DebTemplate == "" { @@ -70,6 +89,9 @@ func (d *Debian) createDebconfTemplate() error { return err } +// createDebconfConfig creates a Debian configuration file. +// +// It takes no parameters and returns an error. func (d *Debian) createDebconfConfig() error { var err error if d.PKGBUILD.DebConfig == "" { @@ -87,6 +109,10 @@ func (d *Debian) createDebconfConfig() error { return err } +// createScripts generates and writes the scripts for the Debian package. +// +// It takes no parameters. +// It returns an error if there was an issue generating or writing the scripts. func (d *Debian) createScripts() error { var err error @@ -123,6 +149,13 @@ func (d *Debian) createScripts() error { return err } +// dpkgDeb generates Debian package files from the given artifact path. +// +// It takes a string parameter `artifactPath` which represents the path where the +// Debian package files will be generated. +// +// The function returns an error if there was an issue generating the Debian package +// files. func (d *Debian) dpkgDeb(artifactPath string) error { var err error @@ -145,6 +178,10 @@ func (d *Debian) dpkgDeb(artifactPath string) error { return err } +// Prepare prepares the Debian package by installing its dependencies using apt-get. +// +// makeDepends: a slice of strings representing the dependencies to be installed. +// Returns an error if there was a problem installing the dependencies. func (d *Debian) Prepare(makeDepends []string) error { args := []string{ "--assume-yes", @@ -159,6 +196,10 @@ func (d *Debian) Prepare(makeDepends []string) error { return err } +// Strip strips binaries from the Debian package. +// +// It does not take any parameters. +// It returns an error if there is any issue during stripping. func (d *Debian) Strip() error { var err error @@ -188,6 +229,14 @@ func (d *Debian) Strip() error { return err } +// Update updates the Debian package list. +// +// It calls the GetUpdates method of the PKGBUILD field of the Debian struct +// to retrieve any updates using the "apt-get" command and the "update" argument. +// If an error occurs during the update, it is returned. +// +// Returns: +// - error: An error if the update fails. func (d *Debian) Update() error { err := d.PKGBUILD.GetUpdates("apt-get", "update") if err != nil { @@ -197,6 +246,15 @@ func (d *Debian) Update() error { return err } +// createDebResources creates the Debian package resources. +// +// It creates the necessary directories and files for the Debian package. +// It also sets the installed size of the package based on the size of the package directory. +// It generates the control file for the package. +// It creates the scripts for the package. +// It creates the debconf template file. +// It creates the debconf config file. +// It returns an error if any of the operations fail. func (d *Debian) createDebResources() error { d.debDir = filepath.Join(d.PKGBUILD.PackageDir, "DEBIAN") err := utils.ExistsMakeDir(d.debDir) @@ -235,6 +293,9 @@ func (d *Debian) createDebResources() error { return err } +// Build builds the Debian package. +// +// It takes the artifactsPath as a parameter and returns an error if any. func (d *Debian) Build(artifactsPath string) error { var err error @@ -288,6 +349,10 @@ func (d *Debian) Install(artifactsPath string) error { return err } +// PrepareEnvironment prepares the environment for the Debian package. +// +// It takes a boolean parameter `golang` which indicates whether or not to set up Go. +// It returns an error if there was a problem during the environment preparation. func (d *Debian) PrepareEnvironment(golang bool) error { var err error diff --git a/pkg/packer/packer.go b/pkg/packer/packer.go index 17601e0..bd3fb57 100644 --- a/pkg/packer/packer.go +++ b/pkg/packer/packer.go @@ -31,9 +31,11 @@ type Packer interface { Update() error } -// GetPackageManager reads the pkgBuild structure and the distro name. It -// returns a Packer interface representing the specialized package manager for -// that distro. +// GetPackageManager returns a Packer interface based on the given package build and distribution. +// +// pkgBuild: A pointer to a pkgbuild.PKGBUILD struct. +// distro: A string representing the distribution. +// Returns a Packer interface. func GetPackageManager(pkgBuild *pkgbuild.PKGBUILD, distro string) Packer { var packageManager Packer diff --git a/pkg/pacman/pacman.go b/pkg/pacman/pacman.go index 94711ab..4cd8261 100644 --- a/pkg/pacman/pacman.go +++ b/pkg/pacman/pacman.go @@ -7,11 +7,17 @@ import ( "github.com/M0Rf30/yap/pkg/utils" ) +// Pacman represents a package manager for the Pacman distribution. +// +// It contains methods for building, installing, and updating packages. type Pacman struct { PKGBUILD *pkgbuild.PKGBUILD pacmanDir string } +// Build builds the Pacman package. +// +// It takes the artifactsPath as a parameter and returns an error if any. func (p *Pacman) Build(artifactsPath string) error { p.pacmanDir = p.PKGBUILD.StartDir @@ -37,6 +43,10 @@ func (p *Pacman) Build(artifactsPath string) error { return nil } +// Install installs the package using the given artifacts path. +// +// artifactsPath: the path where the package artifacts are located. +// error: an error if the installation fails. func (p *Pacman) Install(artifactsPath string) error { var err error @@ -63,6 +73,10 @@ func (p *Pacman) Install(artifactsPath string) error { return err } +// Prepare prepares the Pacman package by getting the dependencies using the PKGBUILD. +// +// makeDepends is a slice of strings representing the dependencies to be included. +// It returns an error if there is any issue getting the dependencies. func (p *Pacman) Prepare(makeDepends []string) error { args := []string{ "-S", @@ -77,6 +91,10 @@ func (p *Pacman) Prepare(makeDepends []string) error { return err } +// PrepareEnvironment prepares the environment for the Pacman. +// +// It takes a boolean parameter `golang` which indicates whether the environment should be prepared for Golang. +// It returns an error if there is any issue in preparing the environment. func (p *Pacman) PrepareEnvironment(golang bool) error { var err error @@ -100,6 +118,10 @@ func (p *Pacman) PrepareEnvironment(golang bool) error { return err } +// Update updates the Pacman package manager. +// +// It retrieves the updates using the GetUpdates method of the PKGBUILD struct. +// It returns an error if there is any issue during the update process. func (p *Pacman) Update() error { err := p.PKGBUILD.GetUpdates("pacman", "-Sy") if err != nil { @@ -109,6 +131,12 @@ func (p *Pacman) Update() error { return err } +// pacmanBuild builds the package using makepkg command. +// +// It executes the makepkg command in the pacman directory and returns an error if any. +// The error is returned as is. +// Returns: +// - error: An error if any occurred during the execution of the makepkg command. func (p *Pacman) pacmanBuild() error { err := utils.Exec(p.pacmanDir, "makepkg", "-f") if err != nil { diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 3dbfd76..2bcd9f1 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -13,8 +13,21 @@ import ( "mvdan.cc/sh/v3/syntax" ) +// OverridePkgver is a variable that allows overriding the PkgVer field in +// PKGBUILD. This can be useful for setting a custom package version. var OverridePkgver string +// ParseFile parses a file and returns a PKGBUILD object and an error. +// +// Parameters: +// - distro: the distribution name. +// - release: the release version. +// - startDir: the starting directory. +// - home: the home directory. +// +// Returns: +// - *pkgbuild.PKGBUILD: the parsed PKGBUILD object. +// - error: an error if any occurred during parsing. func ParseFile(distro, release, startDir, home string) (*pkgbuild.PKGBUILD, error) { home, err := filepath.Abs(home) @@ -64,6 +77,15 @@ func ParseFile(distro, release, startDir, home string) (*pkgbuild.PKGBUILD, erro return pkgBuild, err } +// getSyntaxFile reads and parses the PKGBUILD file into a syntax tree. +// +// Parameters: +// - startDir (string): The directory where the PKGBUILD file is located. +// - home (string): The home directory path for reference during parsing. +// +// Returns: +// - (*syntax.File): The syntax tree representing the PKGBUILD file's structure. +// - (error): An error if issues occur during file reading or parsing. func getSyntaxFile(startDir, home string) (*syntax.File, error) { file, err := utils.Open(filepath.Join(startDir, "PKGBUILD")) if err != nil { @@ -81,6 +103,10 @@ func getSyntaxFile(startDir, home string) (*syntax.File, error) { return pkgbuildSyntax, err } +// parseSyntaxFile parses the given pkgbuildSyntax and populates the pkgBuild object. +// +// It takes in a pkgbuildSyntax object and a pkgBuild object as parameters. +// It returns an error if any error occurs during parsing. func parseSyntaxFile(pkgbuildSyntax *syntax.File, pkgBuild *pkgbuild.PKGBUILD) error { var err error diff --git a/pkg/pkgbuild/pkgbuild.go b/pkg/pkgbuild/pkgbuild.go index da5579a..d89bf5c 100644 --- a/pkg/pkgbuild/pkgbuild.go +++ b/pkg/pkgbuild/pkgbuild.go @@ -65,10 +65,10 @@ type PKGBUILD struct { priorities map[string]int } -// AddItem reads a key and the related data. It checks the key for __ token and -// give to it a priority value. After that, it binds any element (variable, -// array, function) to the current environment. It returns any error if -// encountered. +// AddItem adds an item to the PKGBUILD. +// +// It takes a key string and data of any type as parameters. +// It returns an error. func (pkgBuild *PKGBUILD) AddItem(key string, data any) error { key, priority, err := pkgBuild.parseDirective(key) if err != nil { diff --git a/pkg/project/project.go b/pkg/project/project.go index fae9e46..ed6129a 100644 --- a/pkg/project/project.go +++ b/pkg/project/project.go @@ -23,13 +23,27 @@ var ( UntilPkgName string ) +// DistroProject is an interface that defines the methods for creating and +// preparing a project for a specific distribution. +// +// It includes the following methods: +// - Create(): error +// This method is responsible for creating the project. +// - Prepare(): error +// This method is responsible for preparing the project. type DistroProject interface { Create() error Prepare() error } -// MultipleProject defnes the content of yap.json specfile and some in-memory -// objects. +// MultipleProject represents a collection of projects. +// +// It contains a slice of Project objects and provides methods to interact +// with multiple projects. The methods include building all the projects, +// finding a package in the projects, and creating packages for each project. +// The MultipleProject struct also contains the output directory for the +// packages and the UntilPkgName field, which can be used to stop the build +// process after a specific package. type MultipleProject struct { makeDepends []string packageManager packer.Packer @@ -41,6 +55,12 @@ type MultipleProject struct { Projects []*Project `json:"projects" validate:"required,dive,required"` } +// Project represents a single project. +// +// It contains the necessary information to build and manage the project. +// The fields include the project's name, the path to the project directory, +// the builder object, the package manager object, and a flag indicating +// whether the project has to be installed. type Project struct { Builder *builder.Builder BuildRoot string @@ -54,6 +74,12 @@ type Project struct { HasToInstall bool `json:"install" validate:""` } +// BuildAll builds all the projects in the MultipleProject struct. +// +// It compiles each project's package and creates the necessary packages. +// If the project has to be installed, it installs the package. +// If UntilPkgName is not empty, it stops building after the specified package. +// It returns an error if any error occurs during the build process. func (mpc *MultipleProject) BuildAll() error { if UntilPkgName != "" { mpc.findPackageInProjects() @@ -96,6 +122,9 @@ func (mpc *MultipleProject) BuildAll() error { return nil } +// Clean cleans up the MultipleProject by removing the package directories and +// source directories if the NoCache flag is set. It takes no parameters. It +// returns an error if there was a problem removing the directories. func (mpc *MultipleProject) Clean() error { var err error @@ -118,6 +147,14 @@ func (mpc *MultipleProject) Clean() error { return err } +// MultiProject is a function that performs multiple project operations. +// +// It takes in the following parameters: +// - distro: a string representing the distribution +// - release: a string representing the release +// - path: a string representing the path +// +// It returns an error. func (mpc *MultipleProject) MultiProject(distro, release, path string) error { err := mpc.readProject(path) if err != nil { @@ -159,6 +196,10 @@ func (mpc *MultipleProject) MultiProject(distro, release, path string) error { return err } +// createPackages creates packages for the MultipleProject. +// +// It takes a pointer to a MultipleProject as a receiver and a pointer to a Project as a parameter. +// It returns an error. func (mpc *MultipleProject) createPackages(proj *Project) error { if mpc.Output != "" { mpc.Output, _ = filepath.Abs(mpc.Output) @@ -176,6 +217,11 @@ func (mpc *MultipleProject) createPackages(proj *Project) error { return err } +// findPackageInProjects searches for a package in the MultipleProject struct. +// +// It iterates over the Projects slice and checks if the package name matches +// the value of UntilPkgName. If a match is found, it sets the matchFound variable +// to true. If no match is found, it prints an error message and exits the program. func (mpc *MultipleProject) findPackageInProjects() { var matchFound bool @@ -197,6 +243,11 @@ func (mpc *MultipleProject) findPackageInProjects() { } } +// getMakeDeps retrieves the make dependencies for the MultipleProject. +// +// It iterates over each child project and appends their make dependencies +// to the makeDepends slice. The makeDepends slice is then assigned to the +// makeDepends field of the MultipleProject. func (mpc *MultipleProject) getMakeDeps() { var makeDepends []string @@ -207,6 +258,13 @@ func (mpc *MultipleProject) getMakeDeps() { mpc.makeDepends = makeDepends } +// populateProjects populates the MultipleProject with projects based on the +// given distro, release, and path. +// +// distro: The distribution of the projects. +// release: The release version of the projects. +// path: The path to the projects. +// error: An error if any occurred during the population process. func (mpc *MultipleProject) populateProjects(distro, release, path string) error { var err error @@ -238,6 +296,10 @@ func (mpc *MultipleProject) populateProjects(distro, release, path string) error return err } +// readProject reads the project file at the specified path and populates the MultipleProject struct. +// +// It takes a string parameter `path` which represents the path to the project file. +// It returns an error if there was an issue opening or reading the file, or if the JSON data is invalid. func (mpc *MultipleProject) readProject(path string) error { cleanFilePath := filepath.Clean(filepath.Join(path, "yap.json")) @@ -269,6 +331,9 @@ func (mpc *MultipleProject) readProject(path string) error { return err } +// validateAllProject validates all projects in the MultipleProject struct. +// +// It takes in the distro, release, and path as parameters and returns an error. func (mpc *MultipleProject) validateAllProject(distro, release, path string) error { var err error for _, child := range mpc.Projects { @@ -286,6 +351,10 @@ func (mpc *MultipleProject) validateAllProject(distro, release, path string) err return err } +// validateJSON validates the JSON of the MultipleProject struct. +// +// It uses the validator package to validate the struct and returns any errors encountered. +// It returns an error if the validation fails. func (mpc *MultipleProject) validateJSON() error { validate := validator.New() diff --git a/pkg/redhat/redhat.go b/pkg/redhat/redhat.go index f8b00a3..fb3995a 100644 --- a/pkg/redhat/redhat.go +++ b/pkg/redhat/redhat.go @@ -12,6 +12,10 @@ import ( "github.com/otiai10/copy" ) +// Redhat represents a Redhat package. +// +// It contains the directory path of the package and the PKGBUILD struct, which +// contains the metadata and build instructions for the package. type Redhat struct { PKGBUILD *pkgbuild.PKGBUILD redhatDir string @@ -23,6 +27,9 @@ type Redhat struct { srpmsDir string } +// Build builds the Redhat package. +// +// It takes the artifactsPath as a parameter and returns an error. func (r *Redhat) Build(artifactsPath string) error { r.getArch() r.getGroup() @@ -71,6 +78,12 @@ func (r *Redhat) Build(artifactsPath string) error { return err } +// Install installs the Redhat package to the specified artifacts path. +// +// It takes the following parameter: +// - artifactsPath: The path to the directory where the artifacts are stored. +// +// It returns an error if there was an issue during the installation process. func (r *Redhat) Install(artifactsPath string) error { var err error @@ -98,6 +111,10 @@ func (r *Redhat) Install(artifactsPath string) error { return err } +// PrepareEnvironment prepares the environment for the Redhat struct. +// +// It takes a boolean parameter `golang` which indicates whether or not to set up the Go environment. +// It returns an error if there was an issue with the environment preparation. func (r *Redhat) PrepareEnvironment(golang bool) error { var err error @@ -120,6 +137,10 @@ func (r *Redhat) PrepareEnvironment(golang bool) error { return err } +// Prepare prepares the Redhat instance by installing the required dependencies. +// +// makeDepends is a slice of strings representing the dependencies to be installed. +// It returns an error if there is any issue during the installation process. func (r *Redhat) Prepare(makeDepends []string) error { args := []string{ "-y", @@ -134,12 +155,22 @@ func (r *Redhat) Prepare(makeDepends []string) error { return err } +// Update updates the Redhat object. +// +// It takes no parameters. +// It returns an error. func (r *Redhat) Update() error { var err error return err } +// getFiles retrieves the files from the Redhat package directory and populates the PKGBUILD.Files field. +// +// It iterates over the files in the package directory and adds them to the PKGBUILD.Files slice. +// It also handles the backup paths specified in the PKGBUILD.Backup field. +// +// Returns an error if there is any issue while walking the directory or retrieving the files. func (r *Redhat) getFiles() error { backup := set.NewSet() paths := set.NewSet() @@ -179,34 +210,45 @@ func (r *Redhat) getFiles() error { } for pathInf := range paths.Iter() { - path := pathInf.(string) - - if !strings.HasPrefix(path, "/") { - path = "/" + path + if !strings.HasPrefix(pathInf, "/") { + pathInf = "/" + pathInf } - if backup.Contains(path) { - path = `%config "` + path + `"` + if backup.Contains(pathInf) { + pathInf = `%config "` + pathInf + `"` } else { - path = `"` + path + `"` + pathInf = `"` + pathInf + `"` } - r.PKGBUILD.Files = append(r.PKGBUILD.Files, path) + r.PKGBUILD.Files = append(r.PKGBUILD.Files, pathInf) } return err } +// getArch updates the architecture values in the Redhat struct. +// +// It does not take any parameters. +// It does not return anything. func (r *Redhat) getArch() { for index, arch := range r.PKGBUILD.Arch { r.PKGBUILD.Arch[index] = RPMArchs[arch] } } +// getGroup updates the section of the Redhat struct with the corresponding +// value from the RPMGroups map. +// +// No parameters. +// No return types. func (r *Redhat) getGroup() { r.PKGBUILD.Section = RPMGroups[r.PKGBUILD.Section] } +// getRelease updates the release information of the Redhat struct. +// +// It appends the RPMDistros[r.PKGBUILD.Distro] and r.PKGBUILD.Codename to +// r.PKGBUILD.PkgRel if r.PKGBUILD.Codename is not empty. func (r *Redhat) getRelease() { if r.PKGBUILD.Codename != "" { r.PKGBUILD.PkgRel = r.PKGBUILD.PkgRel + @@ -215,6 +257,10 @@ func (r *Redhat) getRelease() { } } +// makeDirs creates the necessary directories for the Redhat struct. +// +// It does not take any parameters. +// It returns an error if any directory creation fails. func (r *Redhat) makeDirs() error { var err error @@ -244,6 +290,14 @@ func (r *Redhat) makeDirs() error { return err } +// rpmBuild builds an RPM package using the Redhat package manager. +// +// It executes the 'rpmbuild' command with the necessary options and arguments +// to build the RPM package. The package is built using the specified +// specifications file and the resulting package is stored in the Redhat directory. +// +// Returns an error if the 'rpmbuild' command fails to execute or if there +// are any errors during the package building process. func (r *Redhat) rpmBuild() error { err := utils.Exec(r.specsDir, "rpmbuild", diff --git a/pkg/set/set.go b/pkg/set/set.go index a4ac9b1..67ce4a8 100644 --- a/pkg/set/set.go +++ b/pkg/set/set.go @@ -2,22 +2,33 @@ package set var exists = struct{}{} +// Set represents a simple set data structure implemented using a map. type Set struct { m map[string]struct{} } +// Add adds a value to the Set. +// +// value: the value to be added. func (s *Set) Add(value string) { s.m[value] = exists } +// Contains checks if the given value is present in the set. +// +// value: the value to check for. +// bool: true if the value is present, false otherwise. func (s *Set) Contains(value string) bool { _, c := s.m[value] return c } -func (s *Set) Iter() <-chan any { - iter := make(chan any) +// Iter returns a channel that iterates over the elements of the set. +// +// It returns a channel of type string. +func (s *Set) Iter() <-chan string { + iter := make(chan string) go func() { for key := range s.m { @@ -30,6 +41,11 @@ func (s *Set) Iter() <-chan any { return iter } +// NewSet creates a new Set. +// +// It initializes a new Set with an empty map and returns a pointer to it. +// The returned Set is ready to use. +// Returns a pointer to the newly created Set. func NewSet() *Set { s := &Set{ m: make(map[string]struct{}), @@ -38,6 +54,9 @@ func NewSet() *Set { return s } +// Remove removes the specified value from the set. +// +// value: the value to be removed from the set. func (s *Set) Remove(value string) { delete(s.m, value) } diff --git a/pkg/source/source.go b/pkg/source/source.go index 0e4e6b7..b568805 100644 --- a/pkg/source/source.go +++ b/pkg/source/source.go @@ -22,22 +22,43 @@ const ( git = "git" ) +// Source defines all the fields accepted by a source item. type Source struct { - Hash string - RefKey string - RefValue string + // Hash is the integrity hashsum for a source item + Hash string + // RefKey is the reference name for a VCS fragment (branch, tag) declared in the + // URI. i.e: "myfile::git+https://example.com/example.git#branch=example" + RefKey string + // RefValue is the reference value for a VCS fragment declared in the URI. i.e: + // myfile::git+https://example.com/example.git#branch=refvalue + RefValue string + // SourceItemPath is the absolute path to a source item (folder or file) SourceItemPath string - SourceItemURI string - SrcDir string - StartDir string + // SourceItemURI it the full source item URI. i.e: + // "myfile::git+https://example.com/example.git#branch=example" i.e: + // "https://example.com/example.tar.gz" + SourceItemURI string + // SrcDir is the directory where all the source items are symlinked, extracted + // and processed by packaging functions. + SrcDir string + // StartDir is the root where a copied PKGBUILD lives and all the source items + // are downloaded. It generally contains the src and pkg folders. + StartDir string } +// Get retrieves the source from the specified URI and performs necessary operations on it. +// +// It parses the URI, determines the source type, and calls the appropriate getURL function. +// If the source type is not recognized or supported, it prints an error message and exits. +// It then validates the source, creates symbolic links for sources, and extracts the source. +// +// Returns an error if any of the operations fail. func (src *Source) Get() error { var err error src.parseURI() - sourceType := src.getType() + sourceType := src.getProtocol() switch sourceType { case "http": @@ -79,6 +100,13 @@ func (src *Source) Get() error { return err } +// extract extracts the source file to the destination directory. +// +// It opens the source file specified by the SourceItemPath field of the Source struct. +// If the file cannot be opened, it prints an error message and returns the error. +// Otherwise, it unarchives the file to the destination directory specified by the SrcDir field of the Source struct. +// If the unarchiving fails, it prints an error message and panics. +// Finally, it returns any error that occurred during the extraction process. func (src *Source) extract() error { dlFile, err := os.Open(filepath.Join(src.StartDir, src.SourceItemPath)) if err != nil { @@ -101,6 +129,10 @@ func (src *Source) extract() error { return err } +// getReferenceType returns the reference type for the given source. +// +// It takes no parameters. +// It returns a plumbing.ReferenceName. func (src *Source) getReferenceType() plumbing.ReferenceName { var referenceName plumbing.ReferenceName @@ -115,7 +147,17 @@ func (src *Source) getReferenceType() plumbing.ReferenceName { return referenceName } -func (src *Source) getType() string { +// getProtocol returns the protocol of the source item URI. +// +// It checks if the source item URI starts with "http://", "https://", or "ftp://". +// If it does, it returns the corresponding protocol. +// If the source item URI starts with "git+https://", it returns "git". +// Otherwise, it returns "file". +// +// Returns: +// +// string: The protocol of the source item URI. +func (src *Source) getProtocol() string { if strings.HasPrefix(src.SourceItemURI, "http://") { return "http" } @@ -135,6 +177,10 @@ func (src *Source) getType() string { return "file" } +// getURL retrieves the URL for the Source object based on the specified protocol. +// +// protocol: The protocol to use for retrieving the URL. +// Returns: None. func (src *Source) getURL(protocol string) { dloadFilePath := filepath.Join(src.StartDir, src.SourceItemPath) @@ -159,6 +205,11 @@ func (src *Source) getURL(protocol string) { } } +// parseURI parses the URI of the Source and updates the SourceItemPath, +// SourceItemURI, RefKey, and RefValue fields accordingly. +// +// No parameters. +// No return types. func (src *Source) parseURI() { src.SourceItemPath = utils.Filename(src.SourceItemURI) @@ -178,6 +229,9 @@ func (src *Source) parseURI() { } } +// symlinkSources creates a symbolic link from symlinkSource to symLinkTarget. +// +// It returns an error if the symlink creation fails. func (src *Source) symlinkSources() error { var err error @@ -192,8 +246,11 @@ func (src *Source) symlinkSources() error { return err } -// validate checks that items declared in the source array have a valid hashsum. -// It returns any error if encountered. +// validate validates the source by checking its integrity. +// +// It checks the hash of the source file against the expected hash value. +// If the hashes don't match, it returns an error. +// The function takes no parameters and returns an error. func (src *Source) validate() error { info, err := os.Stat(filepath.Join(src.StartDir, src.SourceItemPath)) if err != nil { diff --git a/pkg/utils/file.go b/pkg/utils/file.go index deb464c..cbc5656 100644 --- a/pkg/utils/file.go +++ b/pkg/utils/file.go @@ -9,6 +9,14 @@ import ( "github.com/M0Rf30/yap/pkg/constants" ) +// Chmod changes the file mode of the specified path. +// +// It takes a string parameter `path` which represents the path of the file +// whose mode needs to be changed. It also takes an `os.FileMode` parameter +// `perm` which represents the new file mode to be set. +// +// The function returns an error if there was an issue changing the file +// mode. If the file mode was successfully changed, it returns nil. func Chmod(path string, perm os.FileMode) error { err := os.Chmod(path, perm) if err != nil { @@ -24,6 +32,10 @@ func Chmod(path string, perm os.FileMode) error { return err } +// Create creates a new file at the specified path. +// +// It takes a string parameter `path` which represents the path of the file to be created. +// The function returns a pointer to an `os.File` and an error. func Create(path string) (*os.File, error) { cleanFilePath := filepath.Clean(path) @@ -39,6 +51,13 @@ func Create(path string) (*os.File, error) { return file, err } +// CreateWrite writes the given data to the file specified by the path. +// +// It takes two parameters: +// - path: a string representing the path of the file. +// - data: a string representing the data to be written to the file. +// +// It returns an error if there was a problem creating or writing to the file. func CreateWrite(path, data string) error { file, err := Create(path) if err != nil { @@ -60,12 +79,20 @@ func CreateWrite(path, data string) error { return err } -func Exists(filename string) bool { - _, err := os.Stat(filename) +// Exists checks if a file or directory exists at the given path. +// +// path: the path to the file or directory. +// bool: returns true if the file or directory exists, false otherwise. +func Exists(path string) bool { + _, err := os.Stat(path) return !os.IsNotExist(err) } +// ExistsMakeDir checks if a directory exists at the given path and creates it if it doesn't. +// +// path: the path to the directory. +// error: returns an error if the directory cannot be created or accessed. func ExistsMakeDir(path string) error { _, err := os.Stat(path) if err != nil { @@ -90,6 +117,10 @@ func ExistsMakeDir(path string) error { return err } +// Filename returns the filename from a given path. +// +// It takes a string parameter `path` which represents the path of the file. +// It returns a string which is the filename extracted from the path. func Filename(path string) string { n := strings.LastIndex(path, "/") if n == -1 { @@ -99,6 +130,9 @@ func Filename(path string) string { return path[n+1:] } +// GetDirSize calculates the size of a directory in kilobytes. +// +// It takes a path as a parameter and returns the size of the directory in kilobytes and an error if any. func GetDirSize(path string) (int64, error) { var size int64 @@ -124,6 +158,10 @@ func GetDirSize(path string) (int64, error) { return size, err } +// MkdirAll creates a directory and all its parent directories. +// +// It takes a string parameter `path` which represents the path of the directory to be created. +// The function returns an error if any error occurs during the directory creation process. func MkdirAll(path string) error { //#nosec err := os.MkdirAll(path, 0o755) @@ -140,6 +178,10 @@ func MkdirAll(path string) error { return err } +// Open opens a file at the specified path and returns a pointer to the file and an error. +// +// The path parameter is a string representing the file path to be opened. +// The function returns a pointer to an os.File and an error. func Open(path string) (*os.File, error) { cleanFilePath := filepath.Clean(path) @@ -155,6 +197,10 @@ func Open(path string) (*os.File, error) { return file, err } +// Remove deletes a file or directory at the specified path. +// +// path: the path of the file or directory to be removed. +// Returns an error if the removal fails. func Remove(path string) error { err := os.Remove(path) if err != nil { @@ -170,6 +216,10 @@ func Remove(path string) error { return err } +// RemoveAll removes a file or directory and any children it contains. +// +// path: the path of the file or directory to be removed. +// error: an error if the removal fails. func RemoveAll(path string) error { err := os.RemoveAll(path) if err != nil { diff --git a/pkg/utils/proc.go b/pkg/utils/proc.go index c76eaaa..6e7ef9d 100644 --- a/pkg/utils/proc.go +++ b/pkg/utils/proc.go @@ -5,6 +5,14 @@ import ( "os/exec" ) +// Exec executes a command in the specified directory. +// +// It takes the following parameters: +// - dir: the directory in which the command will be executed. +// - name: the name of the command to be executed. +// - arg: optional arguments to be passed to the command. +// +// It returns an error if the command execution fails. func Exec(dir, name string, arg ...string) error { cmd := exec.Command(name, arg...) cmd.Stdout = os.Stdout @@ -22,6 +30,14 @@ func Exec(dir, name string, arg ...string) error { return err } +// ExecOutput executes a command with the given arguments and returns its output as a string. +// +// It takes the following parameters: +// - dir: the directory in which the command should be executed. +// - name: the name of the command to be executed. +// - arg: a variadic parameter representing the arguments to be passed to the command. +// +// It returns a string representing the output of the command and an error if any occurred. func ExecOutput(dir, name string, arg ...string) (string, error) { cmd := exec.Command(name, arg...) cmd.Stderr = os.Stderr diff --git a/pkg/utils/strings.go b/pkg/utils/strings.go index ead9751..a0b3942 100644 --- a/pkg/utils/strings.go +++ b/pkg/utils/strings.go @@ -11,9 +11,9 @@ import ( "mvdan.cc/sh/v3/syntax" ) -// GenerateRandomString returns a securely generated random string. It will -// return an error if the system's secure random number generator fails to -// function correctly, in which case the caller should not continue. +// GenerateRandomString generates a random string of length n. +// +// It takes an integer n as a parameter and returns a string. func GenerateRandomString(n int) string { const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" @@ -31,8 +31,10 @@ func GenerateRandomString(n int) string { return string(ret) } -// StringifyArray generates a string from a *syntax.Assign of an array -// declaration. +// StringifyArray generates a string representation of an array in the given syntax.Assign node. +// +// node: A pointer to the syntax.Assign node representing the array. +// []string: An array of strings representing the stringified elements of the array. func StringifyArray(node *syntax.Assign) []string { fields := make([]string, 0) printer := syntax.NewPrinter(syntax.Indent(2)) @@ -55,8 +57,10 @@ func StringifyArray(node *syntax.Assign) []string { return fields } -// StringifyAssign generates a string from a *syntax.Assign of a variable -// declaration. +// StringifyAssign returns a string representation of the given *syntax.Assign node. +// +// It takes a pointer to a *syntax.Assign node as its parameter. +// It returns a string. func StringifyAssign(node *syntax.Assign) string { out := &strings.Builder{} printer := syntax.NewPrinter(syntax.Indent(2)) @@ -73,8 +77,9 @@ func StringifyAssign(node *syntax.Assign) string { return strings.Trim(out.String(), "\"") } -// StringifyFuncDecl generates strings from a *syntax.Assign of a function -// declaration. +// StringifyFuncDecl converts a syntax.FuncDecl node to a string representation. +// +// It takes a pointer to a syntax.FuncDecl node as a parameter and returns a string. func StringifyFuncDecl(node *syntax.FuncDecl) string { out := &strings.Builder{} printer := syntax.NewPrinter(syntax.Indent(2)) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 85feb6a..8d99b27 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -17,6 +17,10 @@ import ( const goArchivePath = "/tmp/go.tar.gz" const goExecutable = "/usr/bin/go" +// CheckGO checks if the GO executable is already installed. +// +// It does not take any parameters. +// It returns a boolean value indicating whether the GO executable is already installed. func CheckGO() bool { if _, err := os.Stat(goExecutable); err == nil { fmt.Printf("%s🪛 :: %sGO is already installed%s\n", @@ -30,6 +34,11 @@ func CheckGO() bool { return false } +// Download downloads a file from the given URL and saves it to the specified destination. +// +// Parameters: +// - destination: the path where the downloaded file will be saved. +// - url: the URL of the file to download. func Download(destination, url string) { // create client client := grab.NewClient() @@ -98,6 +107,10 @@ Loop: ) } +// GOSetup sets up the Go environment. +// +// It checks if Go is installed and if not, it downloads and installs it. +// The function takes no parameters and does not return anything. func GOSetup() { if CheckGO() { return @@ -135,6 +148,10 @@ func GOSetup() { string(constants.ColorWhite)) } +// PullContainers pulls the specified container image. +// +// target: the name of the container image to pull. +// error: returns an error if the container image cannot be pulled. func PullContainers(target string) error { containerApp := "/usr/bin/podman" args := []string{ @@ -155,17 +172,21 @@ func PullContainers(target string) error { return err } +// Unarchive extracts files from an archive and saves them to a destination directory. +// +// archiveReader is an io.Reader that represents the archive file. +// destination is the path to the directory where the files will be saved. +// Returns an error if there was a problem extracting the files. func Unarchive(archiveReader io.Reader, destination string) error { format, archiveReader, _ := archiver.Identify("", archiveReader) - // the list of files we want out of the archive; any - // directories will include all their contents unless - // we return fs.SkipDir from our handler - // (leave this nil to walk ALL files from the archive) + + // dirMap is the list of files we want out of the archive; any directories will + // include all their contents unless we return fs.SkipDir from our handler + // (leave this nil to walk ALL files from the archive). dirMap := map[string]bool{} - // not sure if this should be a syncmap, or if a map is ok? - // not sure if the handler itself is invoked serially or if it - // is concurrent? + // not sure if this should be a syncmap, or if a map is ok? not sure if the + // handler itself is invoked serially or if it is concurrent? handler := func(ctx context.Context, archiveFile archiver.File) error { fileName := archiveFile.NameInArchive newPath := filepath.Join(destination, fileName) @@ -184,9 +205,9 @@ func Unarchive(archiveReader io.Reader, destination string) error { if !seenDir { dirMap[fileDir] = true - // linux default for new directories is 777 and let the umask handle - // if should have other controls - //#nosec + // linux default for new directories is 777 and let the umask handle if + // should have other controls. + // #nosec err = os.MkdirAll(fileDir, 0777) }