Skip to content

Commit

Permalink
feat: rpm weak dependencies (artipie#1335)
Browse files Browse the repository at this point in the history
* feat: rpm weak dependencies
  • Loading branch information
olenagerasimova committed Nov 22, 2023
1 parent b435492 commit 3849ca9
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 197 deletions.
3 changes: 2 additions & 1 deletion rpm-adapter/src/main/java/com/artipie/rpm/RpmMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.concurrent.CompletableFuture;
import javax.xml.stream.XMLEventFactory;
import org.codehaus.stax2.XMLOutputFactory2;
import org.redline_rpm.header.AbstractHeader;
import org.redline_rpm.header.Header;

/**
Expand Down Expand Up @@ -347,7 +348,7 @@ public RpmItem(final Header header, final long size, final String dgst,
}

@Override
public Package.MetaHeader header(final Header.HeaderTag tag) {
public Package.MetaHeader header(final AbstractHeader.Tag tag) {
return new FilePackage.EntryHeader(this.header.getEntry(tag));
}

Expand Down
169 changes: 83 additions & 86 deletions rpm-adapter/src/main/java/com/artipie/rpm/meta/XmlEventPrimary.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
package com.artipie.rpm.meta;

import com.artipie.rpm.misc.UncheckedConsumer;
import com.artipie.rpm.pkg.DependencySection;
import com.artipie.rpm.pkg.HeaderTags;
import com.artipie.rpm.pkg.Package;
import com.artipie.rpm.pkg.WeakDepsTags;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -24,6 +26,7 @@
import javax.xml.stream.XMLStreamException;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.redline_rpm.header.Header;

/**
* Implementation of {@link XmlEvent} to build event for {@link XmlPackage#PRIMARY} package.
Expand Down Expand Up @@ -65,6 +68,62 @@ public final class XmlEventPrimary implements XmlEvent {
private static final String NS_URL =
XmlPackage.PRIMARY.xmlNamespaces().get(XmlEventPrimary.PRFX);

/**
* Provides dependencies group.
*/
private static final DependencySection PROVIDES = new DependencySection(
"provides", Header.HeaderTag.PROVIDENAME, Header.HeaderTag.PROVIDEVERSION,
Header.HeaderTag.PROVIDEFLAGS
);

/**
* Conflicts dependencies group.
*/
private static final DependencySection CONFLICTS = new DependencySection(
"conflicts", Header.HeaderTag.CONFLICTNAME, Header.HeaderTag.CONFLICTVERSION,
Header.HeaderTag.CONFLICTFLAGS
);

/**
* Obsoletes dependencies group.
*/
private static final DependencySection OBSOLETES = new DependencySection(
"obsoletes", Header.HeaderTag.OBSOLETENAME, Header.HeaderTag.OBSOLETEVERSION,
Header.HeaderTag.OBSOLETEFLAGS
);

/**
* Recommends dependencies group.
*/
private static final DependencySection RECOMMENDS = new DependencySection(
"recommends", WeakDepsTags.RECOMMENDNAME, WeakDepsTags.RECOMMENDVERSION,
WeakDepsTags.RECOMMENDFLAGS
);

/**
* Suggests dependencies group.
*/
private static final DependencySection SUGGESTS = new DependencySection(
"suggests", WeakDepsTags.SUGGESTNAME, WeakDepsTags.SUGGESTVERSION,
WeakDepsTags.SUGGESTFLAGS
);

/**
* Supplements dependencies group.
*/
private static final DependencySection SUPPLEMENTS = new DependencySection(
"supplements", WeakDepsTags.SUPPLEMENTNAME, WeakDepsTags.SUPPLEMENTVERSION,
WeakDepsTags.SUPPLEMENTFLAGS
);

/**
* Enhances dependencies group.
*/
private static final DependencySection ENHANCES = new DependencySection(
"enhances", WeakDepsTags.ENHANCENAME, WeakDepsTags.ENHANCEVERSION,
WeakDepsTags.ENHANCEFLAGS
);

@Override
public void add(final XMLEventWriter writer, final Package.Meta meta) throws IOException {
final XMLEventFactory events = XMLEventFactory.newFactory();
Expand Down Expand Up @@ -124,10 +183,14 @@ public void add(final XMLEventWriter writer, final Package.Meta meta) throws IOE
new ImmutablePair<>("end", String.valueOf(meta.range()[1]))
).collect(Collectors.toMap(Pair::getKey, Pair::getValue))
);
XmlEventPrimary.addProvides(writer, tags);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.PROVIDES);
XmlEventPrimary.addRequires(writer, tags);
XmlEventPrimary.addObsoletes(writer, tags);
XmlEventPrimary.addConflicts(writer, tags);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.OBSOLETES);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.CONFLICTS);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.RECOMMENDS);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.SUGGESTS);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.SUPPLEMENTS);
XmlEventPrimary.addDependencySection(writer, tags, XmlEventPrimary.ENHANCES);
new Files(XmlEventPrimary.filesFilter()).add(writer, meta);
writer.add(events.createEndElement("", "", "format"));
writer.add(events.createEndElement("", "", "package"));
Expand All @@ -136,40 +199,6 @@ public void add(final XMLEventWriter writer, final Package.Meta meta) throws IOE
}
}

/**
* Builds `provides` tag. Attribute `flags` should be present if the version is present and
* in `provides` the only possible flag value is `EQ`.
*
* @param writer Xml event writer
* @param tags Tag info
* @throws XMLStreamException On error
*/
private static void addProvides(final XMLEventWriter writer, final HeaderTags tags)
throws XMLStreamException {
final XMLEventFactory events = XMLEventFactory.newFactory();
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "provides")
);
final List<String> names = tags.providesNames();
final List<Optional<String>> flags = tags.providesFlags();
final List<HeaderTags.Version> versions = tags.providesVer();
for (int ind = 0; ind < names.size(); ind = ind + 1) {
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "entry")
);
writer.add(events.createAttribute("name", names.get(ind)));
XmlEventPrimary.addEntryAttr(
writer, events, versions, ind, flags, HeaderTags.Flags.EQUAL.notation()
);
writer.add(
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "entry")
);
}
writer.add(
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "provides")
);
}

/**
* Builds `requires` tag. Items with names started on `rpmlib(` or `config(` are excluded,
* duplicates without version are also excluded.
Expand All @@ -186,16 +215,18 @@ private static void addRequires(final XMLEventWriter writer, final HeaderTags ta
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "requires")
);
final List<String> names = tags.requires();
final List<Optional<String>> flags = tags.requireFlags();
final List<String> names = tags.dependencyNames(Header.HeaderTag.REQUIRENAME);
final List<Optional<String>> flags = tags.dependencyFlags(Header.HeaderTag.REQUIREFLAGS);
final List<Integer> intflags = tags.requireFlagsInts();
final List<HeaderTags.Version> versions = tags.requiresVer();
final List<HeaderTags.Version> versions =
tags.dependencyVers(Header.HeaderTag.REQUIREVERSION);
final Map<String, Integer> items = new HashMap<>(names.size());
final Set<String> duplicates = new HashSet<>(names.size());
final Set<String> files = new XmlEvent.Files(XmlEventPrimary.filesFilter()).files(tags);
final List<String> libcso = new ArrayList<>(names.size());
final List<String> nprovides = tags.providesNames();
final List<HeaderTags.Version> vprovides = tags.providesVer();
final List<String> nprovides = tags.dependencyNames(Header.HeaderTag.PROVIDENAME);
final List<HeaderTags.Version> vprovides =
tags.dependencyVers(Header.HeaderTag.PROVIDEVERSION);
for (int ind = 0; ind < names.size(); ind = ind + 1) {
final String name = names.get(ind);
if (XmlEventPrimary.checkRequiresInProvides(
Expand Down Expand Up @@ -260,60 +291,26 @@ private static void addRequires(final XMLEventWriter writer, final HeaderTags ta
}

/**
* Builds `obsoletes` tag.
*
* @param writer Xml event writer
* @param tags Tag info
* @throws XMLStreamException On error
*/
private static void addObsoletes(final XMLEventWriter writer, final HeaderTags tags)
throws XMLStreamException {
final List<String> names = tags.obsoletes();
if (names.isEmpty()) {
return;
}
final XMLEventFactory events = XMLEventFactory.newFactory();
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "obsoletes")
);
final List<Optional<String>> flags = tags.obsoletesFlags();
final List<HeaderTags.Version> versions = tags.obsoletesVer();
for (int ind = 0; ind < names.size(); ind = ind + 1) {
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "entry")
);
writer.add(events.createAttribute("name", names.get(ind)));
XmlEventPrimary.addEntryAttr(
writer, events, versions, ind, flags, HeaderTags.Flags.EQUAL.notation()
);
writer.add(
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "entry")
);
}
writer.add(
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "obsoletes")
);
}

/**
* Builds `conflicts` tag.
* Builds provided dependency section, checking for duplicates.
*
* @param writer Xml event writer
* @param tags Tag info
* @param dep Dependency section to build
* @throws XMLStreamException On error
*/
private static void addConflicts(final XMLEventWriter writer, final HeaderTags tags)
throws XMLStreamException {
final List<String> names = tags.conflicts();
private static void addDependencySection(
final XMLEventWriter writer, final HeaderTags tags, final DependencySection dep
) throws XMLStreamException {
final List<String> names = tags.dependencyNames(dep.tagForNames());
if (names.isEmpty()) {
return;
}
final XMLEventFactory events = XMLEventFactory.newFactory();
writer.add(
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "conflicts")
events.createStartElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, dep.xmlName())
);
final List<Optional<String>> flags = tags.conflictsFlags();
final List<HeaderTags.Version> versions = tags.conflictsVer();
final List<Optional<String>> flags = tags.dependencyFlags(dep.tagForFlags());
final List<HeaderTags.Version> versions = tags.dependencyVers(dep.tagForVersions());
final Set<String> items = new HashSet<>(names.size());
for (int ind = 0; ind < names.size(); ind = ind + 1) {
final String concat = names.get(ind).concat(versions.get(ind).toString())
Expand All @@ -334,7 +331,7 @@ private static void addConflicts(final XMLEventWriter writer, final HeaderTags t
);
}
writer.add(
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, "conflicts")
events.createEndElement(XmlEventPrimary.PRFX, XmlEventPrimary.NS_URL, dep.xmlName())
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* The MIT License (MIT) Copyright (c) 2020-2023 artipie.com
* https://github.com/artipie/artipie/blob/master/LICENSE.txt
*/
package com.artipie.rpm.pkg;

import org.redline_rpm.header.AbstractHeader;

/**
* Rpm package dependency section.
* <a href="https://rpm-software-management.github.io/rpm/manual/tags.html">Tags</a>.
* <a href="https://rpm-software-management.github.io/rpm/manual/dependencies.html">Deps</a>.
* @since 1.11
*/
public final class DependencySection {

/**
* Xml-section name.
*/
private final String name;

/**
* Tag for names.
*/
private final AbstractHeader.Tag names;

/**
* Tag for versions.
*/
private final AbstractHeader.Tag versions;

/**
* Tag for flags.
*/
private final AbstractHeader.Tag flags;

/**
* Ctor.
* @param name Xml-section name
* @param names Tag for names
* @param versions Tag for versions
* @param flags Tag for flags
* @checkstyle ParameterNumberCheck (10 lines)
*/
public DependencySection(
final String name, final AbstractHeader.Tag names, final AbstractHeader.Tag versions,
final AbstractHeader.Tag flags
) {
this.name = name;
this.names = names;
this.versions = versions;
this.flags = flags;
}

/**
* Xml-section name.
* @return String name for xml
*/
public String xmlName() {
return this.name;
}

/**
* Tag for names.
* @return Rpm tag to get deps names
*/
public AbstractHeader.Tag tagForNames() {
return this.names;
}

/**
* Tag for versions.
* @return Rpm tag to get deps versions
*/
public AbstractHeader.Tag tagForVersions() {
return this.versions;
}

/**
* Tag for flags.
* @return Rpm tag to get deps flags
*/
public AbstractHeader.Tag tagForFlags() {
return this.flags;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public Headers(final Header hdr, final Path file, final Digest digest) {
}

@Override
public MetaHeader header(final Header.HeaderTag tag) {
public MetaHeader header(final AbstractHeader.Tag tag) {
return new EntryHeader(this.hdr.getEntry(tag));
}

Expand Down
Loading

0 comments on commit 3849ca9

Please sign in to comment.