mirror of
https://github.com/Fishwaldo/obs-service-set_version.git
synced 2025-03-16 11:51:43 +00:00
Rewrite set_version in python
For the following reasons: - integration of https://github.com/openSUSE/\ obs-service-set_version_pysemver simpler - testsuite is in python - try "import this" to get more reasons :)
This commit is contained in:
parent
5013040029
commit
b5cadd8c1e
2 changed files with 152 additions and 212 deletions
|
@ -10,6 +10,6 @@ python:
|
|||
install:
|
||||
- pip install flake8 ddt unittest2 --use-mirrors
|
||||
script:
|
||||
- flake8 tests/
|
||||
- flake8 set_version tests/
|
||||
- python -m unittest discover tests/
|
||||
|
||||
|
|
362
set_version
362
set_version
|
@ -1,244 +1,184 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# A simple script to update version number in spec, dsc or arch linux files
|
||||
#
|
||||
# (C) 2010 by Adrian Schröter <adrian@suse.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
# See http://www.gnu.org/licenses/gpl-2.0.html for full license text.
|
||||
# (C) 2015 by Thomas Bechtold <tbechtold@suse.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
# See http://www.gnu.org/licenses/gpl-2.0.html for full license text.
|
||||
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tarfile
|
||||
import zipfile
|
||||
|
||||
my $version;
|
||||
my $basename="";
|
||||
my $outdir;
|
||||
my @files;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
use File::Basename;
|
||||
suffixes = ('tar', 'tar.gz', 'tgz', 'tar.bz2', 'tbz2', 'tar.xz', 'zip')
|
||||
suffixes_re = "|".join(map(lambda x: re.escape(x), suffixes))
|
||||
|
||||
sub usage()
|
||||
{
|
||||
print<<END
|
||||
|
||||
Open Build Service source service "set_version"
|
||||
def _get_local_files():
|
||||
""" sorted local file list by modification time (newest first)"""
|
||||
files = glob.glob('*')
|
||||
files.sort(key=lambda x: os.stat(os.path.join(os.getcwd(), x)).st_mtime,
|
||||
reverse=True)
|
||||
return files
|
||||
|
||||
Used to update build description files with a detected or given version number.
|
||||
|
||||
Required:
|
||||
def _get_version_via_filename(files, basename):
|
||||
""" detect version based on file names"""
|
||||
for f in files:
|
||||
regex = r"^%s.*[-_]([\d].*)\.(?:%s)$" % (re.escape(basename),
|
||||
suffixes_re)
|
||||
m = re.match(regex, f)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# Nothing found
|
||||
return None
|
||||
|
||||
--outdir: out put directory for modified sources
|
||||
|
||||
Options:
|
||||
def _get_version(str_list, basename):
|
||||
regex = "%s.*[-_]([\d][^\/]*).*" % basename
|
||||
for s in str_list:
|
||||
m = re.match(regex, s)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# Nothing found
|
||||
return None
|
||||
|
||||
--version: use given version string, do not detect it from source files
|
||||
|
||||
--basename: detect version based on the file name with a given prefix
|
||||
def _get_version_via_archive_dirname(files, basename):
|
||||
""" detect version based tar'd directory name"""
|
||||
for f in filter(lambda x: x.endswith(suffixes), files):
|
||||
# handle tarfiles
|
||||
if tarfile.is_tarfile(f):
|
||||
with tarfile.open(f) as tf:
|
||||
v = _get_version(tf.getnames(), basename)
|
||||
if v:
|
||||
return v
|
||||
# handle zipfiles
|
||||
if zipfile.is_zipfile(f):
|
||||
with zipfile.ZipFile(f, 'r') as zf:
|
||||
v = _get_version(zf.namelist(), basename)
|
||||
if v:
|
||||
return v
|
||||
# Nothing found
|
||||
return None
|
||||
|
||||
--file: modify only this build description. maybe used multiple times.
|
||||
END
|
||||
;
|
||||
exit;
|
||||
}
|
||||
|
||||
while (@ARGV) {
|
||||
usage() if $ARGV[0] eq '--help';
|
||||
if ($ARGV[0] eq '--outdir') {
|
||||
shift @ARGV;
|
||||
$outdir = shift @ARGV;
|
||||
next;
|
||||
} elsif ($ARGV[0] eq '--version') {
|
||||
shift @ARGV;
|
||||
$version = shift @ARGV;
|
||||
next;
|
||||
} elsif ($ARGV[0] eq '--basename') {
|
||||
# this is actually more a prefix
|
||||
shift @ARGV;
|
||||
$basename = shift @ARGV;
|
||||
next;
|
||||
} elsif ($ARGV[0] eq '--file') {
|
||||
shift @ARGV;
|
||||
push @files, shift @ARGV;
|
||||
next;
|
||||
} else {
|
||||
die("Unknown argument $ARGV[0]!");
|
||||
}
|
||||
last;
|
||||
}
|
||||
def _get_version_via_debian_changelog(filename):
|
||||
# from http://anonscm.debian.org/cgit/pkg-python-debian/\
|
||||
# python-debian.git/tree/lib/debian/changelog.py
|
||||
topline = re.compile(r'^(\w%(name_chars)s*) \(([^\(\) \t]+)\)'
|
||||
'((\s+%(name_chars)s+)+)\;'
|
||||
% {'name_chars': '[-+0-9a-z.]'},
|
||||
re.IGNORECASE)
|
||||
if os.path.exists(filename):
|
||||
with open(filename, "r") as f:
|
||||
firstline = f.readline()
|
||||
topmatch = topline.match(firstline)
|
||||
if topmatch:
|
||||
return topmatch.group(2)
|
||||
# Nothing found
|
||||
return None
|
||||
|
||||
usage() unless $outdir;
|
||||
|
||||
# get local file list
|
||||
local *D;
|
||||
opendir(D, ".") || return ();
|
||||
my @srcfiles = grep {$_ ne '.' && $_ ne '..'} readdir(D);
|
||||
closedir D;
|
||||
def _replace_tag(filename, tag, string):
|
||||
# first, modify a copy of filename and then move it
|
||||
filename_new = ".%s" % filename
|
||||
shutil.copy(filename, filename_new)
|
||||
with open(filename_new, 'r+') as f:
|
||||
contents = f.read()
|
||||
f.seek(0)
|
||||
if filename.endswith("PKGBUILD"):
|
||||
contents_new, subs = re.subn(
|
||||
r"^{tag}=.*".format(tag=tag),
|
||||
r"{tag}={string}".format(tag=tag, string=string), contents)
|
||||
else:
|
||||
# keep inline macros for rpm
|
||||
contents_new, subs = re.subn(r'^{tag}:(\s*)[^%]*'.format(tag=tag),
|
||||
r'{tag}:\g<1>{string}'.format(
|
||||
tag=tag, string=string), contents)
|
||||
|
||||
# sorted local file list by modification time (newest first)
|
||||
@srcfiles = sort { -M "$a" <=> -M "$b" } (@srcfiles);
|
||||
if subs > 0:
|
||||
f.truncate()
|
||||
f.write(contents_new)
|
||||
os.rename(filename_new, filename)
|
||||
|
||||
# Detect version based on file names
|
||||
unless ($version) {
|
||||
my @binsufs = qw{tar tar.gz tgz tar.bz2 tbz2 tar.xz zip};
|
||||
my $binsufsre = join('|', map {"\Q$_\E"} @binsufs);
|
||||
for my $name (@srcfiles) {
|
||||
if ($name =~ /^$basename.*[-_]([\d].*)\.(?:$binsufsre)$/) {
|
||||
$version=$1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detect version based tar'd directory name
|
||||
unless ($version) {
|
||||
my @binsufs = qw{tar tar.gz tgz tar.bz2 tbz2 tar.xz zip};
|
||||
my $binsufsre = join('|', map {"\Q$_\E"} @binsufs);
|
||||
for my $name (@srcfiles) {
|
||||
if ($name =~ /$binsufsre$/) {
|
||||
open( FH, "tar tf $name |" );
|
||||
my $line;
|
||||
while (defined($line = <FH>)) {
|
||||
if ($line =~ /$basename.*[-_]([\d][^\/]*)\/.*/) {
|
||||
$version=$1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close( FH );
|
||||
def _replace_debian_changelog_version(filename, version_new):
|
||||
# first, modify a copy of filename and then move it
|
||||
filename_new = ".%s" % filename
|
||||
shutil.copy(filename, filename_new)
|
||||
# get current version
|
||||
version_current = _get_version_via_debian_changelog(filename_new)
|
||||
with open(filename_new, 'r+') as f:
|
||||
content_lines = f.readlines()
|
||||
f.seek(0)
|
||||
content_lines[0] = content_lines[0].replace(
|
||||
version_current, version_new, 1)
|
||||
f.truncate()
|
||||
f.writelines(content_lines)
|
||||
os.rename(filename_new, filename)
|
||||
|
||||
last if $version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detect version based on Debian changelog
|
||||
unless ($version) {
|
||||
if (defined(my $dch = glob("*debian.changelog"))) {
|
||||
open ( FH, "$dch" );
|
||||
my $line = <FH>;
|
||||
if ($line =~ /.*\((.*)\).*/) {
|
||||
$version=$1;
|
||||
}
|
||||
close( FH );
|
||||
}
|
||||
}
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Open Build Service source service "set_version".'
|
||||
'Used to update build description files with a '
|
||||
'detected or given version number.')
|
||||
parser.add_argument('--outdir', required=True,
|
||||
help='output directory for modified sources')
|
||||
parser.add_argument('--version',
|
||||
help='use given version string, do not detect it '
|
||||
'from source files')
|
||||
parser.add_argument('--basename', default="",
|
||||
help='detect version based on the file name with '
|
||||
'a given prefix')
|
||||
parser.add_argument('--file', action='append',
|
||||
help='modify only this build description. '
|
||||
'maybe used multiple times.')
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
# to replace tags in .spec and .dsc files
|
||||
sub replace_tag {
|
||||
my ($filename, $tag, $string) = @_;
|
||||
local *R;
|
||||
local *W;
|
||||
# read, try first an modified version in outdir
|
||||
if (!open(R, '<', "$outdir/$filename")) {
|
||||
if (!open(R, '<', $filename)) {
|
||||
die("unable to read $filename: $!\n");
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
if (!open(W, '>', "$outdir/.$filename")) {
|
||||
die("unable to write .$filename: $!\n");
|
||||
return undef;
|
||||
}
|
||||
my $line;
|
||||
while (defined($line = <R>)) {
|
||||
$line =~ s/\n$//;
|
||||
if ( $filename =~ /PKGBUILD$/ ) {
|
||||
$line =~ s/^$tag=.*/$tag=$string/;
|
||||
} else {
|
||||
# keep inline macros for rpm
|
||||
$line =~ s/^$tag:(\s*)[^%]*/$tag:$1$string/;
|
||||
}
|
||||
print W "$line\n";
|
||||
}
|
||||
close R;
|
||||
close W;
|
||||
version = args['version']
|
||||
|
||||
rename("$outdir/.$filename", "$outdir/$filename") || die("rename failed");
|
||||
}
|
||||
files_local = _get_local_files()
|
||||
|
||||
# to replace version in debian.changelog file
|
||||
sub replace_debian_changelog_version {
|
||||
my ($filename, $string) = @_;
|
||||
local *R;
|
||||
local *W;
|
||||
# read, try first an modified version in outdir
|
||||
if (!open(R, '<', "$outdir/$filename")) {
|
||||
if (!open(R, '<', $filename)) {
|
||||
die("unable to read $filename: $!\n");
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
if (!open(W, '>', "$outdir/.$filename")) {
|
||||
die("unable to write .$filename: $!\n");
|
||||
return undef;
|
||||
}
|
||||
my $line = <R>;
|
||||
# only replace version in the most recent entry (the first line)
|
||||
if ($line =~ /.*\((.*)\).*/) {
|
||||
$line =~ s/$1/$string/;
|
||||
}
|
||||
print W "$line";
|
||||
# copy the rest
|
||||
while (<R>) {
|
||||
print W;
|
||||
}
|
||||
close R;
|
||||
close W;
|
||||
if not version:
|
||||
version = _get_version_via_filename(
|
||||
files_local, args["basename"])
|
||||
if not version:
|
||||
version = _get_version_via_archive_dirname(
|
||||
files_local, args["basename"])
|
||||
if not version:
|
||||
version = _get_version_via_debian_changelog("debian.changelog")
|
||||
|
||||
rename("$outdir/.$filename", "$outdir/$filename") || die("rename failed");
|
||||
}
|
||||
if not version:
|
||||
sys.exit(-1)
|
||||
|
||||
die("No version found or defined") unless $version;
|
||||
# if no files explicitly specified process whole directory
|
||||
files = args['file'] or files_local
|
||||
|
||||
# if no files explicitly specified process whole directory
|
||||
push @files, @srcfiles if @files <= 0;
|
||||
# handle rpm spec and debian dsc files
|
||||
for f in filter(lambda x: x.endswith((".spec", ".dsc")), files):
|
||||
_replace_tag(f, 'Version', version)
|
||||
_replace_tag(f, 'Release', "0")
|
||||
|
||||
# handle rpm spec and debian dsc files
|
||||
for my $file (grep {$_ =~ /.(spec|dsc)$/} @files) {
|
||||
replace_tag($file, 'Version', $version);
|
||||
replace_tag($file, 'Release', "0");
|
||||
}
|
||||
# update debian.changelog file
|
||||
for f in filter(lambda x: x.endswith(("debian.changelog")), files):
|
||||
_replace_debian_changelog_version(f, version)
|
||||
|
||||
# update debian.changelog file
|
||||
for my $file (grep {$_ =~ /.*debian.changelog$/} @files) {
|
||||
replace_debian_changelog_version($file, $version);
|
||||
}
|
||||
|
||||
use Digest::MD5;
|
||||
|
||||
# handle arch linux PKGBUILD files
|
||||
for my $pkgbuild (grep {$_ =~ /PKGBUILD$/} @files) {
|
||||
# find md5sum of tar ball
|
||||
my $md5sum;
|
||||
my $tarfile;
|
||||
for my $file (@srcfiles) {
|
||||
if ( $file =~ /^_service:.*[-_]\Q$version\E.*/ ) {
|
||||
$tarfile = $file;
|
||||
last;
|
||||
}
|
||||
}
|
||||
unless($tarfile) {
|
||||
for my $file (@srcfiles) {
|
||||
if ( $file =~ /.*[-_]\Q$version\E.*/ ) {
|
||||
$tarfile = $file;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open(FILE, $tarfile) || die "Unable to find source file to calculate md5sum\n";
|
||||
my $ctx = Digest::MD5->new;
|
||||
$ctx->addfile(*FILE);
|
||||
$md5sum = $ctx->hexdigest;
|
||||
close(FILE);
|
||||
|
||||
die ("Failed to calculate md5sum") unless $md5sum;
|
||||
replace_tag($pkgbuild, "pkgver", $version);
|
||||
replace_tag($pkgbuild, "pkgrel", "0");
|
||||
replace_tag($pkgbuild, "md5sums", "('".$md5sum."')");
|
||||
}
|
||||
# handle arch linux PKGBUILD files
|
||||
# TODO: Handle the md5sums generation!
|
||||
for f in filter(lambda x: x.endswith(("PKGBUILD")), files):
|
||||
_replace_tag(f, "md5sums", "(SKIP)")
|
||||
|
|
Loading…
Add table
Reference in a new issue