diff --git a/README.md b/README.md index 68cf6f3..720d80e 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ mkdir files 5) Either copy the bpm-create script from the bpm-utils test package into your /usr/local/bin directory or install the bpm-utils.bpm package 6) Run the following ``` -bpm-create +bpm-create ``` 7) It's done! You now hopefully have a working BPM package! ### Source Packages @@ -85,10 +85,11 @@ bpm-create ``` touch source.sh ``` -4) You are able to run bash code in this file. BPM will extract this file in a directory under /tmp and it will be ran there -5) Your goal is to download your program's source code with either git, wget, curl, etc. and put the binaries under a folder called 'output' in the root of the temp directory. There is a simple example script with helpful comments in the htop-src test package -6) As of this moment there is no script to automate package compression like for binary packages. You will need to create the archive manually +4) If you would like to bundle patches or other files with your source package create a 'source-files' directory and place your files in there. They will be extracted to the same location as the source.sh file during compilation +5) You are able to run bash code in source.sh. BPM will extract this file in a directory under /tmp and it will be run there +6) Your goal is to download your program's source code with either git, wget, curl, etc. and put the binaries under a folder called 'output' in the root of the temp directory. There is a simple example script with helpful comments in the htop-src test package +7) When you are done making your source.sh script run the following to create a package archive ``` -tar -czvf my_package-src.bpm pkg.info source.sh +bpm-create ``` -7) That's it! Your source package should now be compiling correctly! \ No newline at end of file +8) That's it! Your source package should now be compiling correctly! \ No newline at end of file diff --git a/bpm_utils/package_utils.go b/bpm_utils/package_utils.go index 461e31c..dc5d6bc 100644 --- a/bpm_utils/package_utils.go +++ b/bpm_utils/package_utils.go @@ -304,6 +304,16 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe } } } else if pkgInfo.Type == "source" { + temp := "/var/tmp/bpm_source-" + pkgInfo.Name + err = os.RemoveAll(temp) + if err != nil { + return err + } + err = os.Mkdir(temp, 0755) + fmt.Println("Creating temp directory at: " + temp) + if err != nil { + return err + } for { header, err := tr.Next() if err == io.EOF { @@ -312,151 +322,186 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe if err != nil { return err } + if strings.HasPrefix(header.Name, "source-files/") && header.Name != "source-files/" { + extractFilename := path.Join(temp, strings.TrimPrefix(header.Name, "source-files/")) + switch header.Typeflag { + case tar.TypeDir: + if err := os.Mkdir(extractFilename, 0755); err != nil { + if !os.IsExist(err) { + return err + } + } else { + fmt.Println("Creating Directory: " + extractFilename) + } + case tar.TypeReg: + err := os.Remove(extractFilename) + if err != nil && !os.IsNotExist(err) { + return err + } + outFile, err := os.Create(extractFilename) + fmt.Println("Creating File: " + extractFilename) + if err != nil { + return err + } + if _, err := io.Copy(outFile, tr); err != nil { + return err + } + if err := os.Chmod(extractFilename, header.FileInfo().Mode()); err != nil { + return err + } + err = outFile.Close() + if err != nil { + return err + } + case tar.TypeSymlink: + fmt.Println("Skipping symlink (Bundling symlinks in source packages is not supported)") + case tar.TypeLink: + fmt.Println("Skipping hard link (Bundling hard links in source packages is not supported)") + default: + return errors.New("ExtractTarGz: unknown type: " + strconv.Itoa(int(header.Typeflag)) + " in " + extractFilename) + } + } if header.Name == "source.sh" { bs, err := io.ReadAll(tr) if err != nil { return err } - temp := "/var/tmp/bpm_source-" + pkgInfo.Name - err = os.RemoveAll(temp) - if err != nil { - return err - } - err = os.Mkdir(temp, 0755) - fmt.Println("Creating temp directory at: " + temp) - if err != nil { - return err - } err = os.WriteFile(path.Join(temp, "source.sh"), bs, 0644) if err != nil { return err } - fmt.Println("Running source.sh file...") - cmd := exec.Command("/usr/bin/sh", "source.sh") - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = temp - err = cmd.Run() + } + } + if _, err := os.Stat(path.Join("source.sh")); os.IsNotExist(err) { + return errors.New("source.sh file could not be found in the temporary build directory") + } + if err != nil { + return err + } + fmt.Println("Running source.sh file...") + cmd := exec.Command("/usr/bin/sh", "source.sh") + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = temp + err = cmd.Run() + if err != nil { + return err + } + if _, err := os.Stat(path.Join(temp, "/output/")); err != nil { + if os.IsNotExist(err) { + return errors.New("Output directory not be found at " + path.Join(temp, "/output/")) + } + return err + } + fmt.Println("Copying all files...") + err = filepath.WalkDir(path.Join(temp, "/output/"), func(fullpath string, d fs.DirEntry, err error) error { + relFilename, err := filepath.Rel(path.Join(temp, "/output/"), fullpath) + if relFilename == "." { + return nil + } + extractFilename := path.Join(installDir, relFilename) + if err != nil { + return err + } + if d.Type() == os.ModeDir { + files = append(files, relFilename+"/") + if err := os.Mkdir(extractFilename, 0755); err != nil { + if !os.IsExist(err) { + return err + } + } else { + fmt.Println("Creating Directory: " + extractFilename) + } + } else if d.Type().IsRegular() { + err := os.Remove(extractFilename) + if err != nil && !os.IsNotExist(err) { + return err + } + outFile, err := os.Create(extractFilename) + fmt.Println("Creating File: " + extractFilename) + files = append(files, relFilename) if err != nil { return err } - if _, err := os.Stat(path.Join(temp, "/output/")); err != nil { - if os.IsNotExist(err) { - return errors.New("Output directory not be found at " + path.Join(temp, "/output/")) - } - return err - } - fmt.Println("Copying all files...") - err = filepath.WalkDir(path.Join(temp, "/output/"), func(fullpath string, d fs.DirEntry, err error) error { - relFilename, err := filepath.Rel(path.Join(temp, "/output/"), fullpath) - if relFilename == "." { - return nil - } - extractFilename := path.Join(installDir, relFilename) - if err != nil { - return err - } - if d.Type() == os.ModeDir { - files = append(files, relFilename+"/") - if err := os.Mkdir(extractFilename, 0755); err != nil { - if !os.IsExist(err) { - return err - } - } else { - fmt.Println("Creating Directory: " + extractFilename) - } - } else if d.Type().IsRegular() { - err := os.Remove(extractFilename) - if err != nil && !os.IsNotExist(err) { - return err - } - outFile, err := os.Create(extractFilename) - fmt.Println("Creating File: " + extractFilename) - files = append(files, relFilename) - if err != nil { - return err - } - f, err := os.Open(fullpath) - if err != nil { - return err - } - if _, err := io.Copy(outFile, f); err != nil { - return err - } - info, err := os.Stat(fullpath) - if err != nil { - return err - } - if err := os.Chmod(extractFilename, info.Mode()); err != nil { - return err - } - err = outFile.Close() - if err != nil { - return err - } - err = f.Close() - if err != nil { - return err - } - } else if d.Type() == os.ModeSymlink { - link, err := os.Readlink(fullpath) - if err != nil { - return err - } - err = os.Remove(extractFilename) - if err != nil && !os.IsNotExist(err) { - return err - } - fmt.Println("Creating Symlink: "+extractFilename, " -> "+link) - files = append(files, relFilename) - err = os.Symlink(link, extractFilename) - if err != nil { - return err - } - } - return nil - }) + f, err := os.Open(fullpath) if err != nil { return err } - if binaryPkgFromSrc { - compiledDir := path.Join(installDir, "var/lib/bpm/compiled/") - err = os.MkdirAll(compiledDir, 755) - compiledInfo := PackageInfo{} - compiledInfo = *pkgInfo - compiledInfo.Type = "binary" - compiledInfo.Arch = GetArch() - err = os.WriteFile(path.Join(compiledDir, "pkg.info"), []byte(CreateInfoFile(compiledInfo)), 0644) - if err != nil { - return err - } - sed := fmt.Sprintf("s/%s/files/", strings.Replace(strings.TrimPrefix(path.Join(temp, "/output/"), "/"), "/", `\/`, -1)) - cmd := exec.Command("/usr/bin/tar", "-czvf", compiledInfo.Name+".bpm", "pkg.info", path.Join(temp, "/output/"), "--transform", sed) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = compiledDir - fmt.Printf("running command: %s %s\n", cmd.Path, strings.Join(cmd.Args, " ")) - err := cmd.Run() - if err != nil { - return err - } - err = os.Remove(path.Join(compiledDir, "pkg.info")) - if err != nil { - return err - } + if _, err := io.Copy(outFile, f); err != nil { + return err } - if !keepTempDir { - err := os.RemoveAll(temp) - if err != nil { - return err - } + info, err := os.Stat(fullpath) + if err != nil { + return err } - if len(files) == 0 { - return errors.New("no output files for source package. Cancelling package installation") + if err := os.Chmod(extractFilename, info.Mode()); err != nil { + return err + } + err = outFile.Close() + if err != nil { + return err + } + err = f.Close() + if err != nil { + return err + } + } else if d.Type() == os.ModeSymlink { + link, err := os.Readlink(fullpath) + if err != nil { + return err + } + err = os.Remove(extractFilename) + if err != nil && !os.IsNotExist(err) { + return err + } + fmt.Println("Creating Symlink: "+extractFilename, " -> "+link) + files = append(files, relFilename) + err = os.Symlink(link, extractFilename) + if err != nil { + return err } } + return nil + }) + if err != nil { + return err + } + if binaryPkgFromSrc { + compiledDir := path.Join(installDir, "var/lib/bpm/compiled/") + err = os.MkdirAll(compiledDir, 755) + compiledInfo := PackageInfo{} + compiledInfo = *pkgInfo + compiledInfo.Type = "binary" + compiledInfo.Arch = GetArch() + err = os.WriteFile(path.Join(compiledDir, "pkg.info"), []byte(CreateInfoFile(compiledInfo)), 0644) + if err != nil { + return err + } + sed := fmt.Sprintf("s/%s/files/", strings.Replace(strings.TrimPrefix(path.Join(temp, "/output/"), "/"), "/", `\/`, -1)) + cmd := exec.Command("/usr/bin/tar", "-czvf", compiledInfo.Name+".bpm", "pkg.info", path.Join(temp, "/output/"), "--transform", sed) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = compiledDir + fmt.Printf("running command: %s %s\n", cmd.Path, strings.Join(cmd.Args, " ")) + err := cmd.Run() + if err != nil { + return err + } + err = os.Remove(path.Join(compiledDir, "pkg.info")) + if err != nil { + return err + } + } + if !keepTempDir { + err := os.RemoveAll(temp) + if err != nil { + return err + } + } + if len(files) == 0 { + return errors.New("no output files for source package. Cancelling package installation") } } else { return errors.New("Unknown package type: " + pkgInfo.Type) diff --git a/main.go b/main.go index ab6c5b0..60fb80d 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,7 @@ import ( /* A simple-to-use package manager */ /* ---------------------------------- */ -var bpmVer = "0.1.1" +var bpmVer = "0.1.2" var subcommand = "help" var subcommandArgs []string diff --git a/test_packages/x86_64/bpm-utils/bpm-utils.bpm b/test_packages/x86_64/bpm-utils/bpm-utils.bpm index 9f45431..21a538b 100644 Binary files a/test_packages/x86_64/bpm-utils/bpm-utils.bpm and b/test_packages/x86_64/bpm-utils/bpm-utils.bpm differ diff --git a/test_packages/x86_64/bpm-utils/files/usr/bin/bpm-create b/test_packages/x86_64/bpm-utils/files/usr/bin/bpm-create index 5396a97..ae72951 100755 --- a/test_packages/x86_64/bpm-utils/files/usr/bin/bpm-create +++ b/test_packages/x86_64/bpm-utils/files/usr/bin/bpm-create @@ -7,7 +7,7 @@ fi output=$1 -if [[ ! "$output" =~ ^[a-zA-Z0-9_-]{1,}$ ]]; then +if [[ ! "$output" =~ ^[a-z.A-Z0-9_-]{1,}$ ]]; then echo "Invalid output name! The name must only contain letters, numbers, hyphens or underscores!" exit 1 fi @@ -22,6 +22,9 @@ else if [ -f source.sh ]; then type="source" echo "source.sh file found" + if [ -d source-files ]; then + echo "source-files/ directory found" + fi else echo "files/ directory or source.sh file not found in $PWD" exit 1 @@ -35,10 +38,14 @@ else exit 1 fi -echo "Creating $type package as $output.bpm" +echo "Creating $type package as $output" if [[ "$type" == "binary" ]]; then - tar -czf "$output".bpm files/ pkg.info + tar -czf "$output" files/ pkg.info else - tar -czf "$output".bpm source.sh pkg.info + if [ -d source-files ]; then + tar -czf "$output" source.sh source-files/ pkg.info + else + tar -czf "$output" source.sh pkg.info + fi fi diff --git a/test_packages/x86_64/bpm-utils/pkg.info b/test_packages/x86_64/bpm-utils/pkg.info index 825a73c..6aa66e3 100644 --- a/test_packages/x86_64/bpm-utils/pkg.info +++ b/test_packages/x86_64/bpm-utils/pkg.info @@ -1,6 +1,6 @@ name: bpm-utils description: Utilities to create BPM packages -version: 1.2.0 +version: 1.3.0 url: https://gitlab.com/bubble-package-manager/bpm/ license: GPL3 architecture: x86_64 diff --git a/test_packages/x86_64/bpm/bpm.bpm b/test_packages/x86_64/bpm/bpm.bpm index e4793c0..3c8f9b6 100644 Binary files a/test_packages/x86_64/bpm/bpm.bpm and b/test_packages/x86_64/bpm/bpm.bpm differ diff --git a/test_packages/x86_64/bpm/files/usr/bin/bpm b/test_packages/x86_64/bpm/files/usr/bin/bpm index 6dd057c..a96d54f 100755 Binary files a/test_packages/x86_64/bpm/files/usr/bin/bpm and b/test_packages/x86_64/bpm/files/usr/bin/bpm differ diff --git a/test_packages/x86_64/bpm/pkg.info b/test_packages/x86_64/bpm/pkg.info index 2659d0e..3e7ef6f 100644 --- a/test_packages/x86_64/bpm/pkg.info +++ b/test_packages/x86_64/bpm/pkg.info @@ -1,6 +1,6 @@ name: bpm description: The Bubble Package Manager -version: 0.1.1 +version: 0.1.2 url: https://gitlab.com/bubble-package-manager/bpm/ license: GPL3 architecture: x86_64