repoman.common package

Submodules

repoman.common.artifact module

This module holds the helper classes to represent an artifact list:

Base_dir
└── $name
    └── $version
        ├── $name-$version.$extension
        └── $name-$version.$extension.sig

This module has the classess that manage a set of artifacts, in a hierarchical fashion, in the order:

name 1-* version 1-* inode 1-* artifact-instance

So that translated to classes, with the first being the placeholder for the whole data structure, is:

ArtifactList 1-* ArtifactName 1-* ArtifactVersion \
1-* ArtifactInode 1-* Artifact

All except the Artifact class are implemented as subclasses of the python dict, so as key-value stores.

For clarification, here’s a dictionary like diagram:

ArtifactList{
    name1: ArtifactName{
        version1: ArtifactVersion{
            inode1: ArtifactInode[Artifact, Artifact, ...]
            inode2: ArtifactInode[...]
        },
        version2: ArtifactVersion{...}
    },
    name2: ArtifactName{...}
}

NOTE:You have to implement at least the Artifact class

class repoman.common.artifact.Artifact(path, temp_dir='/tmp', verify_ssl=True)[source]

Bases: object

__str__()[source]

This string uniquely identifies a artifact file, if two have the same string representation, the must point to the same file or a copy of it, if not, you wrongly generated two artifact with the same version/name and different content

extension
full_name

Unique Artifact Name.

This property should uniquely identify an artifact entity, in the sense that if you have two artifacts with the same full_name they must package the same content or one of them is wrongly generated (the version was not bumped or something).

generate_path()[source]

Returns the theoretical path that the artifact should be, instead of the current path it is.

md5

Lazy md5 calculation.

name
sign(key_path, passwd)[source]

Defines how to sign this artifact, by default with detached signature

type
version
class repoman.common.artifact.ArtifactInode(inode)[source]

Bases: list, object

Simple list, abstracts a set of rpm instances

delete(noop=False)[source]
get_artifacts(regmatch=None, fmatch=None)[source]
class repoman.common.artifact.ArtifactList(name, name_class=<class 'repoman.common.artifact.ArtifactName'>)[source]

Bases: dict, object

Dict of artifacts, by name

add_pkg(artifact, onlyifnewer=False)[source]
delete()[source]

Deletes all the artifacts in this list

delete_version(art_name, art_version)[source]

Removes the given artifact’s version if it’s in the list

Parameters:
  • art_name (str) – Name of the artifact to remove it’s version
  • art_version (str) – Version to remove
Returns:

None

get_artifacts(regmatch=None, fmatch=None, latest=0)[source]

Gets the list of artifacts, filtered or not.

Parameters:
  • regmatch – Regular expression to filter the rpms path with
  • fmatch – Filter function, must return True for packages to be included, or False to be excluded. The package object will be passed as parameter
  • latest – number of latest versions to return (0 for all,)
class repoman.common.artifact.ArtifactName(name, version_class=<class 'repoman.common.artifact.ArtifactVersion'>)[source]

Bases: dict, object

Dict of available versions for an artifact name

add_artifact(artifact, onlyifnewer)[source]
delete(noop=False)[source]
delete_version(version, noop=False)[source]
get_artifacts(regmatch=None, fmatch=None, latest=0)[source]
get_latest(num=1)[source]

Returns the list of available inodes for the latest version if any

class repoman.common.artifact.ArtifactVersion(version, inode_class=<class 'repoman.common.artifact.ArtifactInode'>)[source]

Bases: dict, object

Abstracts a set of artifacts inodes for a version

add_artifact(artifact)[source]
delete(noop=False)[source]
delete_inode(inode, noop=False)[source]
get_artifacts(regmatch=None, fmatch=None)[source]

repoman.common.config module

exception repoman.common.config.BadConfigError[source]

Bases: exceptions.Exception

class repoman.common.config.Config(path=None, section='main')[source]

Bases: object

Configuration object to wrap some config values. It keeps the configuration objects, one with the default values for all the sections and one with all the custom ones (from config files or set after).

The resolution order is:
custom_config(current_section -> main_section) -> default_config(current_section -> main_section)
add_to_section(section, option, value)[source]
get(entry, default=None)[source]
get_section(section)[source]
getarray(entry, default=None)[source]
getboolean(entry, default=None)[source]
getdict(entry, default=None)[source]
getfloat(entry, default=None)[source]
getint(entry, default=None)[source]
load(path)[source]
load_plugins()[source]
set(entry, value)[source]
repoman.common.config.update_conf_from_plugin(config, plugins, prefix)[source]

repoman.common.parser module

When specifying a source for an artifact, you have to do it in this format:

source_type:value[:filter[:filter[...]]]

For each source, it will be expanded, and filtered. An example:

repo:master-nightly:name~ovirt-engine.*:latest=2
class repoman.common.parser.Parser(config, stores)[source]

Bases: object

parse(full_source_str)[source]

Parses the given source sting and returns a list of resolved artifact paths

Parameters:full_source_str (Sting) – Source sting to parse
Return type:list of strings

repoman.common.repo module

This module holds the class and methods to manage a repository.

In our case a repository is not just a yum repository but a set of them and another files, in the following structure:

repository_dir
├── store1_dir
│   └── ...
└── store2_dir
    └── ...
class repoman.common.repo.Repo(path, config)[source]

Bases: object

Represents the repository sctructure, it does not require that the repo has the structure specified in the module doc when loading it, but when adding new rpms or generating the sources it will create the new files in that directory structure.

Configuration options:

  • allowed_repo_paths
    Comma separated list of paths where repositories can be found/created
add_path_extra_dir(dirname)[source]

Adds an extra subdir to the curret path

Parameters:dirname (str) – Name of the extra dir to add
Returns:None
add_path_suffix(suffix)[source]

Adds a suffix to the repo’s path

Parameters:suffix (str) – Suffix to postpend to the repo’s path
Returns:None
add_source(artifact_source)[source]

Generic function to add an artifact to the repo.

Some base (meta-)sources are supported, like:

  • conf:path/to/file: This will include all the sources defined in
    the file path/to/file, it supports shell comments in the file, and empty lines
  • stdin: This will read any sources passd through stdin, with the
    same format as conf: files (cat sources | repoman myrepo add stdin is the same as repoman myrepo add conf:sources)
  • repo-suffix:suffix_string: This allows you to define a suffix
    string for the destination repo, it’s helpful to allow generating custom repos from a base one, when the repoman command is hardcoded (with the combination of stdin source)
  • repo-extra-dir:dirname: This allows you to define an extra subdir
    string for the destination repo, it’s helpful to allow generating custom repos from a base one, when the repoman command is hardcoded (with the combination of stdin source).
Parameters:artifact_source – source string of the artifact to add
delete_old(*args, **kwargs)[source]

Remove any old versions but the latest num_to_keep

Parameters:
  • num_to_keep – Number of versions to keef for each artifact
  • noop – if True will not actually remove anything
load()[source]

Actually load all the stores and load the contents of the repo

parse_source_stream(source_stream)[source]

Given a iterable of sources, add all that apply, skipping comments and empty lines

Parameters:source_stream – iterable with the sources, can be an open file object as returned by open
rebase(new_path)[source]

Changes the root path of the repo

Parameters:new_path (str) – New path to root the repo to
Returns:None
save(*args, **kwargs)[source]

Realize all the changes made so far

repoman.common.repo.cleanup(temp_dir)[source]
repoman.common.repo.loaded(func)[source]

repoman.common.utils module

exception repoman.common.utils.NotSamePackage[source]

Bases: exceptions.Exception

Thrown when trying to compare different packages

repoman.common.utils.cmpfullver(fullver1, fullver2)[source]
Compares version strings in the form:
x.y.z-a.b.c
repoman.common.utils.cmpver(ver1, ver2)[source]

Compares two version in a natural sort ordering fashion (what you usually expect when comparing versions yourself). Thought for version strings in the form:

x.y.z
repoman.common.utils.copy(what, where)[source]

Try to link, try to copy if cross-device

Creates a symlink

Parameters:
  • basepath (str) – Path to creat the simlink on
  • dest (str) – Path not relative to basepath of the destination for the link
  • link (str) – Path relative to basepath of the link itself
Returns:

None

repoman.common.utils.download(path, dest_path, tries=3, verify=True)[source]

Download a package from a url.

repoman.common.utils.extract_sources(rpm_path, dst_dir, with_patches=False)[source]

Extract the source files fro a srcrpm, uses rpm2cpio

Parameters:
  • rpm_path – Path to the srcrpm
  • dst_dir – Destination directory to hold the sources, will create it if it does not exist
  • with_patches – if set to True, extract also the .patch files if any
repoman.common.utils.find_recursive(base_path, fmatch)[source]

Walks a directory recursively and returns the list of files for which fmatch(filename) returns True

repoman.common.utils.get_gpg(homedir='/home/docs/.gnupg', use_agent=False)[source]
repoman.common.utils.get_last(what, num)[source]
repoman.common.utils.get_plugins(plugin_dir=None)[source]

Given a path, returns the importable files and directories in it

repoman.common.utils.gpg_get_keyuid(key_path, gpg=None)[source]
repoman.common.utils.gpg_load_key(key_path, gpg=None)[source]
repoman.common.utils.gpg_unlock(key_path, use_agent=True, passphrase=None, gpg=None)[source]
repoman.common.utils.list_files(path, extension)[source]

Find all the files with the given extension under the given dir

repoman.common.utils.print_busy(prev_pos=0)[source]

Shows a spinning bar when called like this: > i=0 > while True: > i = print_busy(i)

repoman.common.utils.response2str(response)[source]
repoman.common.utils.rsplit(what, separator, num_results=None)[source]
repoman.common.utils.sanitize_file_name(file_name, replacement='_')[source]

Replaces any unwanted characters from the given file or dir name with the given replacement string

Parameters:
  • file_name (str) – file or directory name to sanitize
  • replacement (str) – what to put in place of the bad chars
Returns:

sanitized name with all the bad chars replaced

Return type:

str

Example

>>> sanitize_file_name("I'm an /ugly%#@!")
'I_m an _ugly____'
>>> sanitize_file_name("I'm an /ugly%#@!", replacement='-')
'I-m an -ugly----'
repoman.common.utils.save_file(src_path, dst_path)[source]

Save a file to a specific new path if not there already. Will create the path tree if it does not exist already.

Parameters:
  • src_path – Source path for the package
  • dst_path – New path to save the package to
repoman.common.utils.sign_detached(src_dir, key, passphrase=None)[source]

Create the detached signatures for the files in the specified dir.

Parameters:
  • src_dir – File to sign or directory with files to sign (recursively)
  • key – Key to sign the sources with
  • passphrase – Passphrase for the given key
repoman.common.utils.sign_file(gpg, fname, keyid, passphrase, detach=True)[source]
repoman.common.utils.split(what, separator, num_results=None)[source]
repoman.common.utils.to_human_size(fsize)[source]

Pass a number from bytes, to human readable form, using 1024 multiples.

repoman.common.utils.tryint(mayint)[source]

Tries to cast to int, and returns the same object if failed.