Switched to using rpmspec for version determination in tagless mode:

- Greatly simplified getVersionFromSpec function due to rpmspec usage
- Function now returns error info in case rpmspec shell command goes wrong

-Skip Grube
This commit is contained in:
Skip Grube 2023-02-26 22:59:24 -05:00
parent 2c6d6f0b0a
commit 2eb0768f33
No known key found for this signature in database
GPG Key ID: D391F8393BEA6D9C

View File

@ -855,9 +855,9 @@ func processRPMTagless(pd *data.ProcessData) (*srpmprocpb.ProcessResponse, error
// get name-version-release of tagless repo, only if we're not a module repo:
if !pd.ModuleMode {
nvrString := getVersionFromSpec(md.Name, localPath, pd.Version)
if nvrString == "" {
return nil, fmt.Errorf("Error using rpm or rpmbuild to build SRPM and determine version info! (tagless mode)")
nvrString, err := getVersionFromSpec(md.Name, localPath, pd.Version)
if err != nil {
return nil, err
}
// Set version and release fields we extracted (name|version|release are separated by pipes)
@ -1176,112 +1176,39 @@ func convertMetaData(pkgName string, localRepo string) bool {
// - create a "dummy" SRPM (using dummy sources files we use to populate tarballs from lookaside)
// - extract RPM version info from that SRPM, and return it
// If we are in tagless mode, we need to get a package version somehow!
func getVersionFromSpec(pkgName string, localRepo string, majorVersion int) string {
func getVersionFromSpec(pkgName string, localRepo string, majorVersion int) (string, error) {
// Make sure we have "rpm" and "rpmbuild" and "cp" available in our PATH. Otherwise, this won't work:
_, err := exec.LookPath("rpm")
_, err := exec.LookPath("rpmspec")
if err != nil {
return ""
return "", fmt.Errorf("Error: Could not find rpmspec program in PATH")
}
_, err = exec.LookPath("rpmbuild")
// Read the first file from SPECS/ to get our spec file
// (there should only be one file - we check that it ends in ".spec" just to be sure!)
lsTmp, err := ioutil.ReadDir(fmt.Sprintf("%s/SPECS/", localRepo))
if err != nil {
return ""
return "", err
}
specFile := lsTmp[0].Name()
if !strings.HasSuffix(specFile, ".spec") {
return "", fmt.Errorf("Error, first file found in SPECS/ is not a .spec file! Check the SPECS/ directory in the repo?")
}
_, err = exec.LookPath("cp")
if err != nil {
return ""
}
// create separate temp folder space to do our RPM work - we don't want to accidentally contaminate the main Git area:
rpmBuildPath := fmt.Sprintf("%s_rpm", localRepo)
os.Mkdir(rpmBuildPath, 0o755)
// Copy SOURCES/ and SPECS/ into the temp rpmbuild directory recursively
// Yes, we could create or import an elaborate Go-native way to do this, but damnit this is easier:
cmdArgs := strings.Fields(fmt.Sprintf("cp -rp %s/SOURCES %s/SPECS %s/", localRepo, localRepo, rpmBuildPath))
if err := exec.Command(cmdArgs[0], cmdArgs[1:]...).Run(); err != nil {
log.Println(err)
return ""
}
// Loop through .<package>.metadata and get the file names we need to make our SRPM:
lookAside, err := os.Open(fmt.Sprintf("%s/.%s.metadata", localRepo, pkgName))
if err != nil {
log.Println(err)
return ""
}
// Split file into lines and start processing:
scanner := bufio.NewScanner(lookAside)
scanner.Split(bufio.ScanLines)
// loop through each line, and:
// - isolate the SOURCES/filename entry
// - write out a dummy file of the same name to rpmBuildPath/SOURCES
for scanner.Scan() {
// lookaside source is always the 2nd part of the line (after the long SHA sum)
srcFile := strings.Fields(scanner.Text())[1]
// write a dummy file of the same name into the rpmbuild SOURCES/ directory:
dummyFile, err := os.OpenFile(fmt.Sprintf("%s/%s", rpmBuildPath, srcFile), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return ""
}
writer := bufio.NewWriter(dummyFile)
_, _ = writer.WriteString("This is a dummy lookaside file generated by srpmproc. It is only needed to get a working SRPM and extract version information. Please disregard\n")
writer.Flush()
dummyFile.Close()
}
lookAside.Close()
// Now, call rpmbuild to produce the dummy src file:
// Example: rpmbuild --define "_topdir /tmp/srpmproctmp_httpd1988142783_rpm" -bs /tmp/srpmproctmp_httpd1988142783_rpm/SPECS/*.spec
cmd := exec.Command("rpmbuild", fmt.Sprintf(`--define=_topdir %s`, rpmBuildPath), fmt.Sprintf(`--define=dist .el%d`, majorVersion), "-bs", fmt.Sprintf("%s/SPECS/%s.spec", rpmBuildPath, pkgName))
if err := cmd.Run(); err != nil {
log.Println(err)
return ""
}
// Read the first file from the SRPMS/ folder in rpmBuildPath. It should be the SRPM that rpmbuild produced above
// (there should only be one file - we check that it ends in ".rpm" just to be sure!)
lsTmp, err := ioutil.ReadDir(fmt.Sprintf("%s/SRPMS/", rpmBuildPath))
if err != nil {
log.Println(err)
return ""
}
srpmFile := lsTmp[0].Name()
if !strings.HasSuffix(srpmFile, ".rpm") {
log.Println("Error, file found in dummy SRPMS directory did not have an .rpm extension! Perhaps rpmbuild didn't produce a proper source RPM?")
return ""
}
// Call the rpm binary to extract the version-release info out of it, and tack on ".el<VERSION>" at the end:
cmd = exec.Command("rpm", "-qp", "--qf", `%{NAME}|%{VERSION}|%{RELEASE}\n`, fmt.Sprintf("%s/SRPMS/%s", rpmBuildPath, srpmFile))
// Call the rpmspec binary to extract the version-release info out of it, and tack on ".el<VERSION>" at the end:
cmd := exec.Command("rpmspec", "--srpm", fmt.Sprintf(`--define=dist .el%d`, majorVersion), "-q", "--queryformat", `%{NAME}|%{VERSION}|%{RELEASE}\n`, fmt.Sprintf("%s/SPECS/%s", localRepo, specFile))
nvrTmp, err := cmd.CombinedOutput()
if err != nil {
log.Println("Error running rpm command to extract temporary SRPM name-version-release identifiers.")
log.Println("rpmbuild output: ", string(nvrTmp))
log.Println("rpmbuild command: ", cmd.String())
return ""
return "", fmt.Errorf("Error running rpmspec command to determine RPM name-version-release identifier. \nCommand attempted: %s \nCommand output: %s", cmd.String(), string(nvrTmp))
}
// Pull first line of the rpm command's output to get the name-version-release number (there should only be 1 line)
// Pull first line of the version output to get the name-version-release number (there should only be 1 line)
nvr := string(nvrTmp)
nvr = strings.Fields(nvr)[0]
// Clean up: delete the temporary directory
if err := os.RemoveAll(rpmBuildPath); err != nil {
log.Printf("Error cleaning up temporary RPM directory %s . Non-fatal, continuing anyway...\n", rpmBuildPath)
}
// return name-version-release string we derived:
log.Printf("Derived NVR %s from tagless repo via temporary SRPM build\n", nvr)
return nvr
log.Printf("Derived NVR %s from tagless repo via rpmspec command\n", nvr)
return nvr, nil
}
// We need to loop through the lookaside blob files ("SourcesToIgnore"),