
org.metaeffekt.artifact.resolver.alpine.AlpinePackageReference Maven / Gradle / Ivy
/*
* Copyright 2021-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.metaeffekt.artifact.resolver.alpine;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.metaeffekt.artifact.resolver.generic.FileLocation;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Meant to capture fields crucial to correct package resolution.
* Used by {@link AlpinePackageResolver} and such.
*/
@AllArgsConstructor
@EqualsAndHashCode
@Getter
public class AlpinePackageReference {
private static final Logger LOG = LoggerFactory.getLogger(AlpinePackageReference.class);
private static final Pattern alpineIssuePattern = Pattern.compile("\\s*Alpine\\s*Linux");
private static final Pattern alpineVersionPattern = Pattern.compile("[^()]+(?=\\s*\\)\\s*$)");
/**
* Package name as would be given by the package manager.
*
* Remember that this might be a "subpackage" in the alpine packaging system.
*/
private String pkgname = null;
/**
* Package version, (ideally) as would be given by the package manager.
*/
private String pkgver = null;
/**
* Package's "release number", increments when updating packaging files, subordinate to pkgversion (see doc).
*/
private String pkgrel = null;
/**
* Version number of alpine linux as parsed from wherever we can.
* Note that this should not include prefixes like "v" and just reflect the raw version as closely as possible.
*/
private String alpineVersion = null;
// TODO: write a test for this to check correct extraction of id, ver, rel
public AlpinePackageReference(Artifact artifact) {
// try to ensure it's really alpine linux
if (!Constants.ARTIFACT_TYPE_PACKAGE.equals(artifact.get(Constants.KEY_TYPE))) {
LOG.trace(
"Reference initialization rejects artifact [{}] since attr [{}] is expected to be 'package'.",
artifact,
Constants.KEY_TYPE
);
return;
}
// FIXME: how do we know that this really IS an alpine package at this stage? we should early-abort if it's not
final String issueText = artifact.get(Constants.KEY_ISSUE);
if (issueText == null) {
// probably not an alpine package
LOG.trace(
"Reference initialization rejects artifact [{}] due to missing attribute [{}].",
artifact,
Constants.KEY_ISSUE
);
return;
} else if (!alpineIssuePattern.matcher(issueText).find()) {
// warn but do not abort. we'll just try to parse the issue anyway and see what happens.
LOG.warn(
"Issue of artifact [{}] did not look contain [{}]. Trying anyway.",
artifact,
alpineIssuePattern.pattern()
);
}
// get package's version; note that the artifact will contain [pkgver]-r[pkgrel]
final String rawVersion = artifact.getVersion();
// get pkgname: happyfuntime id disassembly
final String id = artifact.getId();
final String pkgname;
final String pkgver;
final String pkgrel;
if (id.endsWith(rawVersion)) {
pkgname = id.substring(0, id.length() - rawVersion.length() - 1);
final int lastR = rawVersion.lastIndexOf("r");
if (lastR == -1) {
LOG.error(
"Artifact id of [{}] was not formatted with release number in version.",
artifact
);
}
pkgver = rawVersion.substring(0, lastR - 1);
pkgrel = rawVersion.substring(lastR + 1);
} else {
LOG.error(
"Artifact id of [{}] did not end with version as this method expects. Has the format changed?",
artifact
);
return;
}
// get alpineVersion
final Matcher alpineVersionMatcher = alpineVersionPattern.matcher(issueText);
if (!alpineVersionMatcher.find()) {
LOG.error(
"Failed to get alpine version for (supposed alpine package) artifact [{}].",
artifact
);
return;
}
final String alpineVersion = alpineVersionMatcher.toMatchResult().group();
this.pkgname = pkgname;
this.pkgver = pkgver;
this.pkgrel = pkgrel;
this.alpineVersion = alpineVersion;
}
/**
* Names the file in a "hopefully specific enough" way.
*
* Trying to predict and match what abuild srcpkg uses.
*
* @return returns a FileLocation specific to this reference.
*/
public FileLocation deriveFileLocation() {
FileLocation fileLocation = new FileLocation();
fileLocation.setEcosystem("alpine");
String filenameNoExtension = this.getPkgname() + "-" + this.getPkgver() + "-" + this.getPkgrel();
// hope that alpine never changes srcpkg extension away from .src.tar.gz
String filename = filenameNoExtension + ".src.tar.gz";
fileLocation.setFilename(filename);
fileLocation.setDispatchName(getPkgname());
fileLocation.setResourceQualifier("alpine-" + this.getAlpineVersion() + "-" + filenameNoExtension);
if (!fileLocation.isValid()) {
throw new IllegalStateException("File location invalid: " + fileLocation);
}
return fileLocation;
}
public String deriveMarkerFileName(String modifier) {
return String.format("%s-%s-%s-%s.marker", pkgname, pkgver, pkgrel, modifier);
}
@Override
public String toString() {
return "AlpinePackageReference{" +
"pkgname='" + pkgname + '\'' +
", pkgver='" + pkgver + '\'' +
", pkgrel='" + pkgrel + '\'' +
", alpineVersion='" + alpineVersion + '\'' +
'}';
}
public boolean isValid() {
return StringUtils.isNotBlank(pkgname)
&& StringUtils.isNotBlank(pkgver)
&& StringUtils.isNotBlank(pkgrel)
&& StringUtils.isNotBlank(alpineVersion);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy