Hi everyone,

I found some issues with my patch set from 2017-03-29 which I have
fixed with the new patch set as of yesterday. Attached are all 65
patches as tarball. You can also pull the 5.1.1-mutiple-versions branch
from https://github.com/profitbricks/reprepro
Feel free to report bugs on GitHub.

Release Notes
=============

Changes between 2017-03-29 and 2017-04-12:

* Fix typo "could not found" -> "could not find" 
* Fix crash when Limit and Tracking is set
* Fix logging when using Archive option
* Fix tracking data when using move command
* Fix tracking data with Archive option
* Do not archive newly added packages (for downgrades)
* Use database environment to avoid database corruption
* Fix BDB0073 DB_NOTFOUND at del (when copying existing packages)

The test cases were enhanced to also check the tracking information and
some new tests were added.

In case you experience following error:
BDB0088 DB_SECONDARY_BAD: Secondary index inconsistent with primary
you can use the attached reconstruct_secondarydb Python script to
reconstruct the secondary database. (I had the issues that the sorting
of the secondary database was wrong and this inconsistency was only
revealed by the new Archive and Limit option)

In addition, dump_packages is attached to dump the content of the
packages.db and packagenames.db in a human readable format (useful to
compare the result of reconstruct_secondarydb).

-- 
Benjamin Drung
System Developer
Debian & Ubuntu Developer

ProfitBricks GmbH
Greifswalder Str. 207
D - 10405 Berlin

Email: benjamin.dr...@profitbricks.com
URL:  http://www.profitbricks.com

Sitz der Gesellschaft: Berlin.
Registergericht: Amtsgericht Charlottenburg, HRB 125506B.
Geschäftsführer: Andreas Gauger, Achim Weiss.
#!/usr/bin/python3

# Copyright (C) 2017, Benjamin Drung <benjamin.dr...@profitbricks.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Dump the content of packages.db and packagenames.db in human-readable format."""

import os

import debian.debian_support
import bsddb3

def get_package_name(primarykey, primarydata):
    return primarykey.split(b'|')[0] + b'\0'


def debianversioncompare(a, b):
    if a == '' and b == '':
        # TODO: Find reason for this call!
        return 0
    a_version = debian.debian_support.Version(a.decode().rstrip('\0').split('|')[1])
    b_version = debian.debian_support.Version(b.decode().rstrip('\0').split('|')[1])
    if a_version < b_version:
        return 1
    elif a_version == b_version:
        return 0
    else:
        return -1


packages_filename = 'packages.db' if os.path.isfile('packages.db') else 'db/packages.db'
packagenames_filename = 'packagenames.db' if os.path.isfile('packagenames.db') else 'db/packagenames.db'
packages = bsddb3.btopen(packages_filename, 'r')
databases = list(d.decode() for d in packages.keys())
packages.close()

for database in databases:
    db = bsddb3.db.DB()
    db.open(packages_filename, dbname=database, dbtype=bsddb3.db.DB_BTREE)
    for key, value in db.items():
        print("===== {} | {} =====\n{}".format(database, key.decode().strip('\0'),
                                           value.decode().strip('\0')))
    db.close()

for database in databases:
    sec_db = bsddb3.db.DB()
    sec_db.set_flags(bsddb3.db.DB_DUPSORT)
    sec_db.set_dup_compare(debianversioncompare)
    sec_db.open(packagenames_filename, dbname=database, dbtype=bsddb3.db.DB_BTREE)
    for key, value in sec_db.items():
        print("{} | {} -> {}".format(database, key.decode().strip('\0'),
                                     value.decode().strip('\0')))
    db.close()
#!/usr/bin/python3

# Copyright (C) 2017, Benjamin Drung <benjamin.dr...@profitbricks.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Use this script to reconstruct the secondary DB from the primary DB.

import os

import debian.debian_support
import bsddb3

def get_package_name(primarykey, primarydata):
    return primarykey.split(b'|')[0] + b'\0'


def debianversioncompare(a, b):
    if a == '' and b == '':
        # TODO: Find reason for this call!
        return 0
    a_version = debian.debian_support.Version(a.decode().rstrip('\0').split('|')[1])
    b_version = debian.debian_support.Version(b.decode().rstrip('\0').split('|')[1])
    if a_version < b_version:
        return 1
    elif a_version == b_version:
        return 0
    else:
        return -1


if not os.path.isfile('packages_recovery.db'):
    print("Rename packages.db to packages_recovery.db...")
    os.rename('packages.db', 'packages_recovery.db')

packages = bsddb3.btopen('packages_recovery.db', 'r')
databases = list(d.decode() for d in packages.keys())
packages.close()

for db_file in ('packages.db', 'packagenames.db'):
    if os.path.isfile(db_file):
        print("Removing {}...".format(db_file))
        os.remove(db_file)

for database in databases:
    print("Processing '{}' from packages_recovery.db...".format(database))
    recovery_db = bsddb3.db.DB()
    recovery_db.open('packages_recovery.db', dbname=database)
    db = bsddb3.db.DB()
    db.open('packages.db', dbname=database, dbtype=bsddb3.db.DB_BTREE, flags=bsddb3.db.DB_CREATE)
    sec_db = bsddb3.db.DB()
    sec_db.set_flags(bsddb3.db.DB_DUPSORT)
    sec_db.set_dup_compare(debianversioncompare)
    sec_db.open('packagenames.db', dbname=database, dbtype=bsddb3.db.DB_BTREE,
                flags=bsddb3.db.DB_CREATE)
    db.associate(sec_db, get_package_name)
    items = 0
    for key, value in recovery_db.items():
        db.put(key, value)
        items += 1
    print("Added {} items to '{}'.".format(items, database))
    recovery_db.close()
    db.close()
    sec_db.close()

if os.path.isfile('db/packages.secondary.db'):
    os.rename('db/packages.secondary.db', 'db/packagenames.db')

Attachment: multiple-versions-patches.tar.xz
Description: application/xz-compressed-tar

Reply via email to