mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-14 06:50:39 +00:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 898f726659 | |||
| 5a9e13265f | |||
| 17f5afb494 | |||
| d87fc1be21 | |||
| c3b3e580bd | |||
| abc117531d | |||
| 03b800882c | |||
| 6ffc6056c4 | |||
| 2fe8f5cc1a | |||
| a738d4843d | |||
| 86f3a0b463 | |||
| 121f93957d | |||
| be3cd88a31 | |||
| 81d75ccba4 | |||
| a3df28ec4b | |||
| 06ed37225a | |||
| a9cb70dc08 | |||
| 845ef28a79 | |||
| c9e8d98e37 | |||
| 1728691462 | |||
| 4197af902e | |||
| 656dddda53 | |||
| e1ca459329 | |||
| 7ec27ad88c | |||
| e21506d373 | |||
| e183ddb981 | |||
| c61a6b6dd8 | |||
| 211cce1a8e | |||
| 362cdbcd57 | |||
| 0f902ee74b | |||
| f1d892c759 | |||
| ce5f277f36 | |||
| 9b4ea531d2 | |||
| 69b48de0af | |||
| 99621119e8 | |||
| aa803efd28 | |||
| b48ebbae81 | |||
| 4fea570f5e | |||
| cf12c0b751 | |||
| bbec7ef948 | |||
| 311c8ca6ad | |||
| 33a8dcdacd | |||
| a8e6251a80 | |||
| 326d589f56 | |||
| 7adc065bb8 | |||
| 640c9fe8bd | |||
| 81d6325730 | |||
| 8ece5368b1 | |||
| 7afcc93507 | |||
| e63bbe839b | |||
| 49c8c8bdc0 | |||
| e70517b9ca | |||
| d66fe47def | |||
| 667703a9ac | |||
| 1268f744ab | |||
| d684c87fd1 | |||
| f9853de144 | |||
| b144227fdf | |||
| 7e11e5c652 | |||
| 9ca005147c | |||
| c0b41a7e96 | |||
| 335298d074 | |||
| c903633363 | |||
| 5bf015b2b7 | |||
| 01338d6037 | |||
| 356187f3ae | |||
| 645bba1924 | |||
| 10da8330b0 | |||
| ba30a42d6d | |||
| 6412bee952 | |||
| f168feb9b8 | |||
| 4e2fce7251 | |||
| e37fe33203 | |||
| 5dbb771ba8 | |||
| 4969c31e38 | |||
| b1e9b82ce3 | |||
| 275db14b9f | |||
| 5ccbd232f4 | |||
| 82c06f78f7 | |||
| 4aa24048d5 | |||
| 06f1c62ef0 | |||
| 2c5dcde29d |
+3
-1
@@ -23,4 +23,6 @@ _testmain.go
|
|||||||
*.test
|
*.test
|
||||||
|
|
||||||
coverage.html
|
coverage.html
|
||||||
coverage*.out
|
coverage*.out
|
||||||
|
|
||||||
|
*.pyc
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ GOVERSION=$(shell go version | awk '{print $$3;}')
|
|||||||
ifeq ($(TRAVIS), true)
|
ifeq ($(TRAVIS), true)
|
||||||
GOVERALLS?=$(HOME)/gopath/bin/goveralls
|
GOVERALLS?=$(HOME)/gopath/bin/goveralls
|
||||||
SRCPATH?=$(HOME)/gopath/src
|
SRCPATH?=$(HOME)/gopath/src
|
||||||
|
BINPATH=$(HOME)/gopath/bin
|
||||||
else
|
else
|
||||||
GOVERALLS?=goveralls
|
GOVERALLS?=goveralls
|
||||||
SRCPATH?=$(GOPATH)/src
|
SRCPATH?=$(GOPATH)/src
|
||||||
|
BINPATH?=$(GOPATH)/bin
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(GOVERSION), go1.2)
|
ifeq ($(GOVERSION), go1.2)
|
||||||
@@ -16,13 +18,11 @@ TRAVIS_TARGET=test
|
|||||||
PREPARE_LIST=
|
PREPARE_LIST=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: test check
|
all: test check system-test
|
||||||
|
|
||||||
prepare: $(PREPARE_LIST)
|
prepare: $(PREPARE_LIST)
|
||||||
go get -d -v ./...
|
go get -d -v ./...
|
||||||
go get launchpad.net/gocheck
|
go get launchpad.net/gocheck
|
||||||
# temporary fix: use commander develop version for now (https://github.com/smira/aptly/pull/1)
|
|
||||||
cd $(SRCPATH)/github.com/gonuts/commander && git fetch && git checkout develop
|
|
||||||
|
|
||||||
cover-prepare:
|
cover-prepare:
|
||||||
go get github.com/golang/lint/golint
|
go get github.com/golang/lint/golint
|
||||||
@@ -45,7 +45,11 @@ check:
|
|||||||
go tool vet -all=true .
|
go tool vet -all=true .
|
||||||
golint .
|
golint .
|
||||||
|
|
||||||
travis: $(TRAVIS_TARGET)
|
system-test:
|
||||||
|
go install
|
||||||
|
PATH=$(BINPATH):$(PATH) python system/run.py
|
||||||
|
|
||||||
|
travis: $(TRAVIS_TARGET) system-test
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -v ./... -gocheck.v=true
|
go test -v ./... -gocheck.v=true
|
||||||
|
|||||||
+8
-341
@@ -10,14 +10,17 @@ aptly
|
|||||||
|
|
||||||
Aptly is a swiss army knife for Debian repository management.
|
Aptly is a swiss army knife for Debian repository management.
|
||||||
|
|
||||||
It allows to: ("+" means planned features)
|
Documentation is available at `http://www.aptly.info/ <http://www.aptly.info/>`_. For support use
|
||||||
|
mailing list `aptly-discuss <https://groups.google.com/forum/#!forum/aptly-discuss>`_.
|
||||||
|
|
||||||
|
Aptly features: ("+" means planned features)
|
||||||
|
|
||||||
* make mirrors of remote Debian/Ubuntu repositories, limiting by components/architectures
|
* make mirrors of remote Debian/Ubuntu repositories, limiting by components/architectures
|
||||||
* take snapshots of mirrors at any point in time, fixing state of repository at some moment of time
|
* take snapshots of mirrors at any point in time, fixing state of repository at some moment of time
|
||||||
* publish snapshot as Debian repository, ready to be consumed by apt
|
* publish snapshot as Debian repository, ready to be consumed by apt
|
||||||
|
* controlled update of one or more packages in snapshot from upstream mirror, tracking dependencies
|
||||||
* merge two or more snapshots into one (+)
|
* merge two or more snapshots into one (+)
|
||||||
* filter repository by search query, pulling dependencies when required (+)
|
* filter repository by search query, pulling dependencies when required (+)
|
||||||
* controlled update of one or more packages in snapshot from upstream mirror, tracking dependencies (+)
|
|
||||||
* publish self-made packages as Debian repositories (+)
|
* publish self-made packages as Debian repositories (+)
|
||||||
|
|
||||||
Current limitations:
|
Current limitations:
|
||||||
@@ -29,347 +32,11 @@ Current limitations:
|
|||||||
|
|
||||||
Currently aptly is under heavy development, so please use it with care.
|
Currently aptly is under heavy development, so please use it with care.
|
||||||
|
|
||||||
.. contents::
|
|
||||||
|
|
||||||
Download
|
Download
|
||||||
--------
|
--------
|
||||||
|
|
||||||
TBD
|
Binary executables (depends almost only on libc) are available for download from `Bintray <http://dl.bintray.com/smira/aptly/>`_.
|
||||||
|
|
||||||
Configuration
|
If you have Go environment set up, you can build aptly from source by running::
|
||||||
-------------
|
|
||||||
|
|
||||||
aptly looks for configuration file in ``/etc/aptly.conf`` and ``~/.aptly.conf``, if no config file found,
|
go get github.com/smira/aptly
|
||||||
new one is created. Also aptly needs root directory for database, package and published repository storage.
|
|
||||||
If not specified, directory defaults to ``~/.aptly``, it will be created if missing.
|
|
||||||
|
|
||||||
Configuration file is stored in JSON format::
|
|
||||||
|
|
||||||
{
|
|
||||||
"rootDir": "/var/aptly",
|
|
||||||
"downloadConcurrency": 4
|
|
||||||
}
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
* ``rootDir`` is root of directory storage to store datbase (``rootDir/db``), downloaded packages (``rootDir/pool``) and
|
|
||||||
published repositories (``rootDir/public``)
|
|
||||||
* ``downloadConcurrency`` is a number of parallel download threads to use when downloading packages
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
Create mirror::
|
|
||||||
|
|
||||||
$ aptly mirror create --architecture="amd64" debian-main http://ftp.ru.debian.org/debian/ squeeze main
|
|
||||||
2013/12/28 19:44:45 Downloading http://ftp.ru.debian.org/debian/dists/squeeze/Release...
|
|
||||||
...
|
|
||||||
|
|
||||||
Mirror [debian-main]: http://ftp.ru.debian.org/debian/ squeeze successfully added.
|
|
||||||
You can run 'aptly mirror update debian-main' to download repository contents.
|
|
||||||
|
|
||||||
Take snapshot::
|
|
||||||
|
|
||||||
$ aptly snapshot create debian-3112 from mirror debian-main
|
|
||||||
|
|
||||||
Snapshot debian-3112 successfully created.
|
|
||||||
You can run 'aptly publish snapshot debian-3112' to publish snapshot as Debian repository.
|
|
||||||
|
|
||||||
Publish snapshot (requires generated GPG key)::
|
|
||||||
|
|
||||||
$ aptly publish snapshot debian-3112
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
Snapshot back has been successfully published.
|
|
||||||
Please setup your webserver to serve directory '/var/aptly/public' with autoindexing.
|
|
||||||
Now you can add following line to apt sources:
|
|
||||||
deb http://your-server/ squeeze main
|
|
||||||
Don't forget to add your GPG key to apt with apt-key.
|
|
||||||
|
|
||||||
Set up webserver (e.g. nginx)::
|
|
||||||
|
|
||||||
server {
|
|
||||||
root /home/example/.aptly/public;
|
|
||||||
server_name mirror.local;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
autoindex on;
|
|
||||||
}
|
|
||||||
|
|
||||||
Add new repository to apt's sources::
|
|
||||||
|
|
||||||
deb http://mirror.local/ squeeze main
|
|
||||||
|
|
||||||
Run apt-get to fetch repository metadata::
|
|
||||||
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
Enjoy!
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
Aptly supports commands in three basic categories:
|
|
||||||
|
|
||||||
* ``mirror``
|
|
||||||
* ``snapshot``
|
|
||||||
* ``publish``
|
|
||||||
|
|
||||||
Command ``mirror``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Mirror subcommands manage mirrors of remote Debian repositories.
|
|
||||||
|
|
||||||
``aptly mirror create``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Creates mirror of remote repository. It supports only HTTP repositories.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly mirror create <name> <archive url> <distribution> [<component1> ...]
|
|
||||||
|
|
||||||
Params are:
|
|
||||||
|
|
||||||
* ``name`` is a name that would be used in aptly to reference this mirror
|
|
||||||
* ``archive url`` is a root of archive, e.g. http://ftp.ru.debian.org/debian/
|
|
||||||
* ``distribution`` is a distribution name, e.g. ``squeeze``
|
|
||||||
* ``component1`` is an optional list of components to download, if not
|
|
||||||
specified aptly would fetch all components, e.g. ``main``
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
* ``--architecture="i386,amd64"`` list of architectures to fetch, if not specified,
|
|
||||||
aptly would fetch packages for all architectures
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly mirror create --architecture="amd64" debian-main http://ftp.ru.debian.org/debian/ squeeze main
|
|
||||||
2013/12/28 19:44:45 Downloading http://ftp.ru.debian.org/debian/dists/squeeze/Release...
|
|
||||||
...
|
|
||||||
|
|
||||||
Mirror [debian-main]: http://ftp.ru.debian.org/debian/ squeeze successfully added.
|
|
||||||
You can run 'aptly mirror update debian-main' to download repository contents.
|
|
||||||
|
|
||||||
``aptly mirror update``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Updates (fetches packages and meta) remote mirror. When mirror is created, it should be run for the
|
|
||||||
first time to fetch mirror contents. This command could be run many times. If interrupted, it could
|
|
||||||
be restarted in a safe way.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly mirror update <name>
|
|
||||||
|
|
||||||
Params are:
|
|
||||||
|
|
||||||
* ``name`` is a mirror name (given when mirror was created)
|
|
||||||
|
|
||||||
All packages would be stored under aptly's root dir (see section on Configuration).
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly mirror update debian-main
|
|
||||||
|
|
||||||
2013/12/29 18:32:34 Downloading http://ftp.ru.debian.org/debian/dists/squeeze/Release...
|
|
||||||
2013/12/29 18:32:37 Downloading http://ftp.ru.debian.org/debian/dists/squeeze/main/binary-amd64/Packages.bz2...
|
|
||||||
2013/12/29 18:37:19 Downloading http://ftp.ru.debian.org/debian/pool/main/libg/libgwenhywfar/libgwenhywfar47-dev_3.11.3-1_amd64.deb...
|
|
||||||
....
|
|
||||||
|
|
||||||
``aptly mirror list``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Shows list of registered mirrors of repositories.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly mirror list
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly mirror list
|
|
||||||
List of mirrors:
|
|
||||||
* [backports]: http://mirror.yandex.ru/backports.org/ squeeze-backports
|
|
||||||
* [debian-main]: http://ftp.ru.debian.org/debian/ squeeze
|
|
||||||
|
|
||||||
To get more information about repository, run `aptly mirror show <name>`.
|
|
||||||
|
|
||||||
``aptly mirror show``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Shows detailed information about mirror.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly mirror show <name>
|
|
||||||
|
|
||||||
Params are:
|
|
||||||
|
|
||||||
* ``name`` is a mirror name (given when mirror was created)
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly mirror show backports2
|
|
||||||
Name: backports2
|
|
||||||
Archive Root URL: http://mirror.yandex.ru/backports.org/
|
|
||||||
Distribution: squeeze-backports
|
|
||||||
Components: main, contrib, non-free
|
|
||||||
Architectures: i386, amd64
|
|
||||||
Last update: 2013-12-27 19:30:19 MSK
|
|
||||||
Number of packages: 3898
|
|
||||||
|
|
||||||
Information from release file:
|
|
||||||
...
|
|
||||||
|
|
||||||
In detailed information, one can see basiс parameters of the mirror, filters by component & architecture, timestamp
|
|
||||||
of last successful repository fetch and number of packages.
|
|
||||||
|
|
||||||
Command ``snapshot``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Snapshot is a fixed state of remote repository. Internally snapshot is list of packages with explicit version.
|
|
||||||
Snapshot is immutable, i.e. it can't change since it has been created.
|
|
||||||
|
|
||||||
``aptly snapshot create .. from mirror``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Creates snapshot from current state of remote mirror. Mirros should be updated at least once before using this command.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly snapshot create <name> from mirror <mirror-name>
|
|
||||||
|
|
||||||
Params are:
|
|
||||||
|
|
||||||
* ``name`` is a name for the snapshot to be created
|
|
||||||
* ``mirror-name`` is a mirror name (given when mirror was created)
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly snapshot create monday-updates from mirror backports2
|
|
||||||
|
|
||||||
Snapshot monday-updates successfully created.
|
|
||||||
You can run 'aptly publish snapshot monday-updates' to publish snapshot as Debian repository.
|
|
||||||
|
|
||||||
``aptly snapshot list``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Displays list of all created snapshots.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly snapshot list
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly snapshot list
|
|
||||||
List of snapshots:
|
|
||||||
* [monday-updates]: Snapshot from mirror [backports2]: http://mirror.yandex.ru/backports.org/ squeeze-backports
|
|
||||||
* [back]: Snapshot from mirror [backports2]: http://mirror.yandex.ru/backports.org/ squeeze-backports
|
|
||||||
|
|
||||||
To get more information about snapshot, run `aptly snapshot show <name>`.
|
|
||||||
|
|
||||||
With snapshot information, basic information about snapshot origin is displayed: which mirror it has been created from.
|
|
||||||
|
|
||||||
``aptly snapshot show``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Shows detailed information about snapshot. Full list of packages in the snapshot is displayed as well.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly snapshot show <name>
|
|
||||||
|
|
||||||
Params:
|
|
||||||
|
|
||||||
* ``name`` is snapshot name which has been given during snapshot creation
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
Name: back
|
|
||||||
Created At: 2013-12-24 15:39:29 MSK
|
|
||||||
Description: Snapshot from mirror [backports2]: http://mirror.yandex.ru/backports.org/ squeeze-backports
|
|
||||||
Number of packages: 3898
|
|
||||||
Packages:
|
|
||||||
altos-1.0.3~bpo60+1_i386
|
|
||||||
amanda-client-1:3.3.1-3~bpo60+1_amd64
|
|
||||||
...
|
|
||||||
|
|
||||||
Command ``publish``
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Publishing snapshot as Debian repository which could be served by HTTP/FTP/rsync server. Repository is signed by
|
|
||||||
user's key with GnuPG. Key should be created beforehand (see section GPG Keys). Published repository could
|
|
||||||
be consumed directly by apt.
|
|
||||||
|
|
||||||
``aptly publish snapshot``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Published repositories appear under ``rootDir/public`` directory.
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
$ aptly publish snapshot <name> [<prefix>]
|
|
||||||
|
|
||||||
Params:
|
|
||||||
|
|
||||||
* ``name`` is a snapshot name that snould be published
|
|
||||||
* ``prefix`` is an optional prefix for publishing, if not specified, repository would be published to the root of
|
|
||||||
publiс directory
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
* ``-architectures=""``: list of architectures to publish (comma-separated); derived automatically from
|
|
||||||
snapshot contents
|
|
||||||
* ``-component=""``: component name to publish; guessed from original repository (if any), or defaults to
|
|
||||||
main
|
|
||||||
* ``-distribution=""``: distribution name to publish; guessed from original repository distribution
|
|
||||||
* ``-gpg-key=""``: GPG key ID to use when signing the release, if not specified default key is used
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ aptly publish snapshot back
|
|
||||||
Signing file '/var/aptly/public/dists/squeeze-backports/Release' with gpg, please enter your passphrase when prompted:
|
|
||||||
|
|
||||||
<<gpg asks for passphrase>>
|
|
||||||
|
|
||||||
Clearsigning file '/var/aptly/public/dists/squeeze-backports/Release' with gpg, please enter your passphrase when prompted:
|
|
||||||
|
|
||||||
<<gpg asks for passphrase>>
|
|
||||||
|
|
||||||
Snapshot back has been successfully published.
|
|
||||||
Please setup your webserver to serve directory '/var/aptly/public' with autoindexing.
|
|
||||||
Now you can add following line to apt sources:
|
|
||||||
deb http://your-server/ squeeze-backports main
|
|
||||||
Don't forget to add your GPG key to apt with apt-key.
|
|
||||||
|
|
||||||
Directory structure for published repositories::
|
|
||||||
|
|
||||||
public/ - root of published tree (root for webserver)
|
|
||||||
dists/
|
|
||||||
squeeze/ - distribution name
|
|
||||||
Release - raw file
|
|
||||||
InRelease - clearsigned file
|
|
||||||
Release.gpg - signature for Release file
|
|
||||||
binary-i386/
|
|
||||||
Packages - list of metadata for packages
|
|
||||||
Packages.gz
|
|
||||||
Packages.bz2
|
|
||||||
pool/
|
|
||||||
main/ - component name
|
|
||||||
m/
|
|
||||||
mars-invaders/
|
|
||||||
mars-invaders_1.0.3_i386.deb - package (hard link to package from main pool)
|
|
||||||
|
|
||||||
GPG Keys
|
|
||||||
--------
|
|
||||||
|
|
||||||
GPG key is required to sign any published repository. Key should be generated before publishing first repository.
|
|
||||||
|
|
||||||
Key generation, storage, backup and revocation is out of scope of this document, there are many tutorials available,
|
|
||||||
e.g. `this one <http://fedoraproject.org/wiki/Creating_GPG_Keys>`_.
|
|
||||||
|
|
||||||
Publiс part of the key should be exported (``gpg --export --armor``) and imported into apt keyring on all machines that would be using
|
|
||||||
published repositories using ``apt-key``.
|
|
||||||
|
|||||||
+35
-28
@@ -5,6 +5,8 @@ import (
|
|||||||
"github.com/gonuts/commander"
|
"github.com/gonuts/commander"
|
||||||
"github.com/gonuts/flag"
|
"github.com/gonuts/flag"
|
||||||
"github.com/smira/aptly/debian"
|
"github.com/smira/aptly/debian"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,15 +17,27 @@ func aptlyMirrorList(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("List of mirrors:\n")
|
|
||||||
|
|
||||||
repoCollection := debian.NewRemoteRepoCollection(context.database)
|
repoCollection := debian.NewRemoteRepoCollection(context.database)
|
||||||
repoCollection.ForEach(func(repo *debian.RemoteRepo) error {
|
|
||||||
fmt.Printf(" * %s\n", repo)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Printf("\nTo get more information about repository, run `aptly mirror show <name>`.\n")
|
if repoCollection.Len() > 0 {
|
||||||
|
fmt.Printf("List of mirrors:\n")
|
||||||
|
repos := make(sort.StringSlice, repoCollection.Len())
|
||||||
|
i := 0
|
||||||
|
repoCollection.ForEach(func(repo *debian.RemoteRepo) error {
|
||||||
|
repos[i] = repo.String()
|
||||||
|
i++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(repos)
|
||||||
|
for _, repo := range repos {
|
||||||
|
fmt.Printf(" * %s\n", repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nTo get more information about mirror, run `aptly mirror show <name>`.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No mirrors found, create one with `aptly mirror create ...`.\n")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,13 +48,7 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var architectures []string
|
repo, err := debian.NewRemoteRepo(args[0], args[1], args[2], args[3:], context.architecturesList)
|
||||||
archs := cmd.Flag.Lookup("architecture").Value.String()
|
|
||||||
if len(archs) > 0 {
|
|
||||||
architectures = strings.Split(archs, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
repo, err := debian.NewRemoteRepo(args[0], args[1], args[2], args[3:], architectures)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create mirror: %s", err)
|
return fmt.Errorf("unable to create mirror: %s", err)
|
||||||
}
|
}
|
||||||
@@ -94,9 +102,10 @@ func aptlyMirrorShow(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\nInformation from release file:\n")
|
fmt.Printf("\nInformation from release file:\n")
|
||||||
for name, value := range repo.Meta {
|
for _, k := range utils.StrMapSortedKeys(repo.Meta) {
|
||||||
fmt.Printf("%s: %s\n", name, value)
|
fmt.Printf("%s: %s\n", k, repo.Meta[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,20 +153,18 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
func makeCmdMirrorCreate() *commander.Command {
|
func makeCmdMirrorCreate() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlyMirrorCreate,
|
Run: aptlyMirrorCreate,
|
||||||
UsageLine: "create",
|
UsageLine: "create <name> <archive url> <distribution> [<component1> ...]",
|
||||||
Short: "create new mirror of Debian repository",
|
Short: "create new mirror of Debian repository",
|
||||||
Long: `
|
Long: `
|
||||||
create only stores metadata about new mirror, and fetches Release files (it doesn't download packages)
|
Create records information about new mirror and fetches Release file (it doesn't download packages).
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
$ aptly mirror create <name> <archive url> <distribution> [<component1> ...]
|
$ aptly mirror create wheezy-main http://mirror.yandex.ru/debian/ wheezy main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-mirror-create", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-mirror-create", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
cmd.Flag.String("architecture", "", "limit architectures to download, comma-delimited list")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCmdMirrorList() *commander.Command {
|
func makeCmdMirrorList() *commander.Command {
|
||||||
@@ -166,7 +173,7 @@ func makeCmdMirrorList() *commander.Command {
|
|||||||
UsageLine: "list",
|
UsageLine: "list",
|
||||||
Short: "list mirrors of remote repositories",
|
Short: "list mirrors of remote repositories",
|
||||||
Long: `
|
Long: `
|
||||||
list shows full list of remote repositories.
|
List shows full list of remote repositories.
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
$ aptly mirror list
|
$ aptly mirror list
|
||||||
@@ -181,13 +188,13 @@ ex:
|
|||||||
func makeCmdMirrorShow() *commander.Command {
|
func makeCmdMirrorShow() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlyMirrorShow,
|
Run: aptlyMirrorShow,
|
||||||
UsageLine: "show",
|
UsageLine: "show <name>",
|
||||||
Short: "show details about remote repository mirror",
|
Short: "show details about remote repository mirror",
|
||||||
Long: `
|
Long: `
|
||||||
show shows full information about mirror.
|
Show shows full information about mirror.
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
$ aptly mirror show <name>
|
$ aptly mirror show wheezy-main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-mirror-show", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-mirror-show", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
@@ -198,13 +205,13 @@ ex:
|
|||||||
func makeCmdMirrorUpdate() *commander.Command {
|
func makeCmdMirrorUpdate() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlyMirrorUpdate,
|
Run: aptlyMirrorUpdate,
|
||||||
UsageLine: "update",
|
UsageLine: "update <name>",
|
||||||
Short: "update packages from remote mirror",
|
Short: "update packages from remote mirror",
|
||||||
Long: `
|
Long: `
|
||||||
Update downloads list of packages and packages themselves.
|
Update downloads list of packages and package files.
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
$ aptly mirror update <name>
|
$ aptly mirror update wheezy-main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-mirror-update", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-mirror-update", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
|
|||||||
+125
-13
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/gonuts/flag"
|
"github.com/gonuts/flag"
|
||||||
"github.com/smira/aptly/debian"
|
"github.com/smira/aptly/debian"
|
||||||
"github.com/smira/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ func aptlyPublishSnapshot(cmd *commander.Command, args []string) error {
|
|||||||
prefix = ""
|
prefix = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishedCollecton := debian.NewPublishedRepoCollection(context.database)
|
||||||
|
|
||||||
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
snapshot, err := snapshotCollection.ByName(name)
|
snapshot, err := snapshotCollection.ByName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,21 +65,29 @@ func aptlyPublishSnapshot(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var architecturesList []string
|
|
||||||
architectures := cmd.Flag.Lookup("architectures").Value.String()
|
|
||||||
if architectures != "" {
|
|
||||||
architecturesList = strings.Split(architectures, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
signer := &utils.GpgSigner{}
|
signer := &utils.GpgSigner{}
|
||||||
signer.SetKey(cmd.Flag.Lookup("gpg-key").Value.String())
|
signer.SetKey(cmd.Flag.Lookup("gpg-key").Value.String())
|
||||||
|
|
||||||
published := debian.NewPublishedRepo(prefix, distribution, component, architecturesList, snapshot)
|
published, err := debian.NewPublishedRepo(prefix, distribution, component, context.architecturesList, snapshot)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to publish: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate := publishedCollecton.CheckDuplicate(published)
|
||||||
|
if duplicate != nil {
|
||||||
|
publishedCollecton.LoadComplete(duplicate, snapshotCollection)
|
||||||
|
return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate)
|
||||||
|
}
|
||||||
|
|
||||||
packageCollection := debian.NewPackageCollection(context.database)
|
packageCollection := debian.NewPackageCollection(context.database)
|
||||||
err = published.Publish(context.packageRepository, packageCollection, signer)
|
err = published.Publish(context.packageRepository, packageCollection, signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("unable to publish: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = publishedCollecton.Add(published)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to save to DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prefix != "" && !strings.HasSuffix(prefix, "/") {
|
if prefix != "" && !strings.HasSuffix(prefix, "/") {
|
||||||
@@ -92,33 +103,134 @@ func aptlyPublishSnapshot(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func aptlyPublishList(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) != 0 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
publishedCollecton := debian.NewPublishedRepoCollection(context.database)
|
||||||
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
|
|
||||||
|
if publishedCollecton.Len() == 0 {
|
||||||
|
fmt.Printf("No snapshots have been published. Publish a snapshot by running `aptly publish snapshot ...`.\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
published := make(sort.StringSlice, 0, publishedCollecton.Len())
|
||||||
|
|
||||||
|
err = publishedCollecton.ForEach(func(repo *debian.PublishedRepo) error {
|
||||||
|
err := publishedCollecton.LoadComplete(repo, snapshotCollection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
published = append(published, repo.String())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load list of repos: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(published)
|
||||||
|
|
||||||
|
fmt.Printf("Published repositories:\n")
|
||||||
|
|
||||||
|
for _, description := range published {
|
||||||
|
fmt.Printf(" * %s\n", description)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func aptlyPublishDrop(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) < 1 || len(args) > 2 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
distribution := args[0]
|
||||||
|
prefix := "."
|
||||||
|
|
||||||
|
if len(args) == 2 {
|
||||||
|
prefix = args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
publishedCollecton := debian.NewPublishedRepoCollection(context.database)
|
||||||
|
|
||||||
|
err = publishedCollecton.Remove(context.packageRepository, prefix, distribution)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to remove: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func makeCmdPublishSnapshot() *commander.Command {
|
func makeCmdPublishSnapshot() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlyPublishSnapshot,
|
Run: aptlyPublishSnapshot,
|
||||||
UsageLine: "snapshot",
|
UsageLine: "snapshot <name> [<prefix>]",
|
||||||
Short: "makes Debian repository out of snapshot",
|
Short: "makes Debian repository out of snapshot",
|
||||||
Long: `
|
Long: `
|
||||||
Publishes snapshot as Debian repository ready to be used by apt tools.
|
Command publish oublishes snapshot as Debian repository ready to be used by apt tools.
|
||||||
|
|
||||||
ex:
|
ex.
|
||||||
$ aptly publish snapshot <name> [<prefix>]
|
$ aptly publish snapshot wheezy-main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-publish-snapshot", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-publish-snapshot", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
cmd.Flag.String("distribution", "", "distribution name to publish")
|
cmd.Flag.String("distribution", "", "distribution name to publish")
|
||||||
cmd.Flag.String("component", "", "component name to publish")
|
cmd.Flag.String("component", "", "component name to publish")
|
||||||
cmd.Flag.String("architectures", "", "list of architectures to publish (comma-separated)")
|
|
||||||
cmd.Flag.String("gpg-key", "", "GPG key ID to use when signing the release")
|
cmd.Flag.String("gpg-key", "", "GPG key ID to use when signing the release")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeCmdPublishDrop() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlyPublishDrop,
|
||||||
|
UsageLine: "drop <distribution> [<prefix>]",
|
||||||
|
Short: "removes files of published repository",
|
||||||
|
Long: `
|
||||||
|
Command removes whatever has been published under specified prefix and distribution name.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly publish drop wheezy
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-publish-drop", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCmdPublishList() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlyPublishList,
|
||||||
|
UsageLine: "list",
|
||||||
|
Short: "displays list of published repositories",
|
||||||
|
Long: `
|
||||||
|
Display command displays list of currently published snapshots with information about published root.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly publish list
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-publish-list", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func makeCmdPublish() *commander.Command {
|
func makeCmdPublish() *commander.Command {
|
||||||
return &commander.Command{
|
return &commander.Command{
|
||||||
UsageLine: "publish",
|
UsageLine: "publish",
|
||||||
Short: "manage published repositories",
|
Short: "manage published repositories",
|
||||||
Subcommands: []*commander.Command{
|
Subcommands: []*commander.Command{
|
||||||
makeCmdPublishSnapshot(),
|
makeCmdPublishSnapshot(),
|
||||||
|
makeCmdPublishList(),
|
||||||
|
makeCmdPublishDrop(),
|
||||||
},
|
},
|
||||||
Flag: *flag.NewFlagSet("aptly-publish", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-publish", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
|
|||||||
+492
-16
@@ -5,6 +5,9 @@ import (
|
|||||||
"github.com/gonuts/commander"
|
"github.com/gonuts/commander"
|
||||||
"github.com/gonuts/flag"
|
"github.com/gonuts/flag"
|
||||||
"github.com/smira/aptly/debian"
|
"github.com/smira/aptly/debian"
|
||||||
|
"github.com/wsxiaoys/terminal/color"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
|
func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
|
||||||
@@ -52,16 +55,31 @@ func aptlySnapshotList(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("List of snapshots:\n")
|
|
||||||
|
|
||||||
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error {
|
|
||||||
fmt.Printf(" * %s\n", snapshot)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Printf("\nTo get more information about snapshot, run `aptly snapshot show <name>`.\n")
|
if snapshotCollection.Len() > 0 {
|
||||||
|
fmt.Printf("List of snapshots:\n")
|
||||||
|
|
||||||
|
snapshots := make(sort.StringSlice, snapshotCollection.Len())
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error {
|
||||||
|
snapshots[i] = snapshot.String()
|
||||||
|
i++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(snapshots)
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
fmt.Printf(" * %s\n", snapshot)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nTo get more information about snapshot, run `aptly snapshot show <name>`.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\nNo snapshots found, create one with `aptly snapshot create...`.\n")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func aptlySnapshotShow(cmd *commander.Command, args []string) error {
|
func aptlySnapshotShow(cmd *commander.Command, args []string) error {
|
||||||
@@ -107,16 +125,391 @@ func aptlySnapshotShow(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) < 1 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
|
packageCollection := debian.NewPackageCollection(context.database)
|
||||||
|
|
||||||
|
snapshots := make([]*debian.Snapshot, len(args))
|
||||||
|
for i := range snapshots {
|
||||||
|
snapshots[i], err = snapshotCollection.ByName(args[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to verify: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(snapshots[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to verify: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packageList, err := debian.NewPackageListFromRefList(snapshots[0].RefList(), packageCollection)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("unable to load packages: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcePackageList := debian.NewPackageList()
|
||||||
|
err = sourcePackageList.Append(packageList)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("unable to merge sources: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < len(snapshots); i++ {
|
||||||
|
pL, err := debian.NewPackageListFromRefList(snapshots[i].RefList(), packageCollection)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("unable to load packages: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sourcePackageList.Append(pL)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("unable to merge sources: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcePackageList.PrepareIndex()
|
||||||
|
|
||||||
|
var architecturesList []string
|
||||||
|
|
||||||
|
if len(context.architecturesList) > 0 {
|
||||||
|
architecturesList = context.architecturesList
|
||||||
|
} else {
|
||||||
|
architecturesList = packageList.Architectures()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(architecturesList) == 0 {
|
||||||
|
return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
|
||||||
|
}
|
||||||
|
|
||||||
|
missing, err := packageList.VerifyDependencies(context.dependencyOptions, architecturesList, sourcePackageList)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to verify dependencies: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missing) == 0 {
|
||||||
|
fmt.Printf("All dependencies are satisfied.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Missing dependencies (%d):\n", len(missing))
|
||||||
|
deps := make(sort.StringSlice, len(missing))
|
||||||
|
i := 0
|
||||||
|
for _, dep := range missing {
|
||||||
|
deps[i] = dep.String()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(deps)
|
||||||
|
|
||||||
|
for _, dep := range deps {
|
||||||
|
fmt.Printf(" %s\n", dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) < 4 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
noDeps := cmd.Flag.Lookup("no-deps").Value.Get().(bool)
|
||||||
|
|
||||||
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
|
packageCollection := debian.NewPackageCollection(context.database)
|
||||||
|
|
||||||
|
// Load <name> snapshot
|
||||||
|
snapshot, err := snapshotCollection.ByName(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to pull: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(snapshot)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to pull: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load <source> snapshot
|
||||||
|
source, err := snapshotCollection.ByName(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to pull: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(source)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to pull: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Dependencies would be pulled into snapshot:\n %s\nfrom snapshot:\n %s\nand result would be saved as new snapshot %s.\n",
|
||||||
|
snapshot, source, args[2])
|
||||||
|
|
||||||
|
// Convert snapshot to package list
|
||||||
|
fmt.Printf("Loading packages (%d)...\n", snapshot.RefList().Len()+source.RefList().Len())
|
||||||
|
packageList, err := debian.NewPackageListFromRefList(snapshot.RefList(), packageCollection)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcePackageList, err := debian.NewPackageListFromRefList(source.RefList(), packageCollection)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Building indexes...\n")
|
||||||
|
packageList.PrepareIndex()
|
||||||
|
sourcePackageList.PrepareIndex()
|
||||||
|
|
||||||
|
// Calculate architectures
|
||||||
|
var architecturesList []string
|
||||||
|
|
||||||
|
if len(context.architecturesList) > 0 {
|
||||||
|
architecturesList = context.architecturesList
|
||||||
|
} else {
|
||||||
|
architecturesList = packageList.Architectures()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(architecturesList) == 0 {
|
||||||
|
return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial dependencies out of arguments
|
||||||
|
initialDependencies := make([]debian.Dependency, len(args)-3)
|
||||||
|
for i, arg := range args[3:] {
|
||||||
|
initialDependencies[i], err = debian.ParseDependency(arg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse argument: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform pull
|
||||||
|
for _, arch := range architecturesList {
|
||||||
|
dependencies := make([]debian.Dependency, len(initialDependencies), 128)
|
||||||
|
for i := range dependencies {
|
||||||
|
dependencies[i] = initialDependencies[i]
|
||||||
|
dependencies[i].Architecture = arch
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go over list of initial dependencies + list of dependencies found
|
||||||
|
for i := 0; i < len(dependencies); i++ {
|
||||||
|
dep := dependencies[i]
|
||||||
|
|
||||||
|
// Search for package that can satisfy dependencies
|
||||||
|
pkg := sourcePackageList.Search(dep)
|
||||||
|
if pkg == nil {
|
||||||
|
color.Printf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|", &dep, source)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all packages with the same name and architecture
|
||||||
|
for p := packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name}); p != nil; {
|
||||||
|
packageList.Remove(p)
|
||||||
|
color.Printf("@r[-]@| %s removed", p)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
p = packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new discovered package
|
||||||
|
packageList.Add(pkg)
|
||||||
|
color.Printf("@g[+]@| %s added", pkg)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
|
||||||
|
if noDeps {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find missing dependencies for single added package
|
||||||
|
pL := debian.NewPackageList()
|
||||||
|
pL.Add(pkg)
|
||||||
|
|
||||||
|
missing, err := pL.VerifyDependencies(context.dependencyOptions, []string{arch}, packageList)
|
||||||
|
if err != nil {
|
||||||
|
color.Printf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|", pkg, err)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append missing dependencies to the list of dependencies to satisfy
|
||||||
|
for _, misDep := range missing {
|
||||||
|
found := false
|
||||||
|
for _, d := range dependencies {
|
||||||
|
if d == misDep {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
dependencies = append(dependencies, misDep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Flag.Lookup("dry-run").Value.Get().(bool) {
|
||||||
|
fmt.Printf("\nNot creating snapshot, as dry run was requested.\n")
|
||||||
|
} else {
|
||||||
|
// Create <destination> snapshot
|
||||||
|
destination := debian.NewSnapshotFromPackageList(args[2], []*debian.Snapshot{snapshot, source}, packageList,
|
||||||
|
fmt.Sprintf("Pulled into '%s' with '%s' as source, pull request was: '%s'", snapshot.Name, source.Name, strings.Join(args[3:], " ")))
|
||||||
|
|
||||||
|
err = snapshotCollection.Add(destination)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create snapshot: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func aptlySnapshotDiff(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) != 2 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyMatching := cmd.Flag.Lookup("only-matching").Value.Get().(bool)
|
||||||
|
|
||||||
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
|
packageCollection := debian.NewPackageCollection(context.database)
|
||||||
|
|
||||||
|
// Load <name-a> snapshot
|
||||||
|
snapshotA, err := snapshotCollection.ByName(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot A: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(snapshotA)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot A: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load <name-b> snapshot
|
||||||
|
snapshotB, err := snapshotCollection.ByName(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot B: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(snapshotB)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot B: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate diff
|
||||||
|
diff, err := snapshotA.RefList().Diff(snapshotB.RefList(), packageCollection)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to calculate diff: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(diff) == 0 {
|
||||||
|
fmt.Printf("Snapshots are identical.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" Arch | Package | Version in A | Version in B\n")
|
||||||
|
for _, pdiff := range diff {
|
||||||
|
if onlyMatching && (pdiff.Left == nil || pdiff.Right == nil) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var verA, verB, pkg, arch, code string
|
||||||
|
|
||||||
|
if pdiff.Left == nil {
|
||||||
|
verA = "-"
|
||||||
|
verB = pdiff.Right.Version
|
||||||
|
pkg = pdiff.Right.Name
|
||||||
|
arch = pdiff.Right.Architecture
|
||||||
|
} else {
|
||||||
|
pkg = pdiff.Left.Name
|
||||||
|
arch = pdiff.Left.Architecture
|
||||||
|
verA = pdiff.Left.Version
|
||||||
|
if pdiff.Right == nil {
|
||||||
|
verB = "-"
|
||||||
|
} else {
|
||||||
|
verB = pdiff.Right.Version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pdiff.Left == nil {
|
||||||
|
code = "@g+@|"
|
||||||
|
} else {
|
||||||
|
if pdiff.Right == nil {
|
||||||
|
code = "@r-@|"
|
||||||
|
} else {
|
||||||
|
code = "@y!@|"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
color.Printf(code+" %-6s | %-40s | %-40s | %-40s\n", arch, pkg, verA, verB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func aptlySnapshotMerge(cmd *commander.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) < 2 {
|
||||||
|
cmd.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotCollection := debian.NewSnapshotCollection(context.database)
|
||||||
|
|
||||||
|
sources := make([]*debian.Snapshot, len(args)-1)
|
||||||
|
|
||||||
|
for i := 0; i < len(args)-1; i++ {
|
||||||
|
sources[i], err = snapshotCollection.ByName(args[i+1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snapshotCollection.LoadComplete(sources[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load snapshot: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := sources[0].RefList()
|
||||||
|
|
||||||
|
for i := 1; i < len(sources); i++ {
|
||||||
|
result = result.Merge(sources[i].RefList())
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceDescription := make([]string, len(sources))
|
||||||
|
for i, s := range sources {
|
||||||
|
sourceDescription[i] = fmt.Sprintf("'%s'", s.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create <destination> snapshot
|
||||||
|
destination := debian.NewSnapshotFromRefList(args[0], sources, result,
|
||||||
|
fmt.Sprintf("Merged from sources: %s", strings.Join(sourceDescription, ", ")))
|
||||||
|
|
||||||
|
err = snapshotCollection.Add(destination)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create snapshot: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func makeCmdSnapshotCreate() *commander.Command {
|
func makeCmdSnapshotCreate() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlySnapshotCreate,
|
Run: aptlySnapshotCreate,
|
||||||
UsageLine: "create",
|
UsageLine: "create <name> from mirror <mirror-name>",
|
||||||
Short: "creates snapshot out of any mirror",
|
Short: "creates snapshot out of any mirror",
|
||||||
Long: `
|
Long: `
|
||||||
Create makes persistent immutable snapshot of repository mirror state in givent moment of time.
|
Command create makes persistent immutable snapshot of remote repository mirror. Snapshot could be
|
||||||
|
published or further modified using merge, pull and other aptly features.
|
||||||
|
|
||||||
ex:
|
ex.
|
||||||
$ aptly snapshot create <name> from mirror <mirror-name>
|
$ aptly snapshot create wheezy-main-today from mirror wheezy-main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-snapshot-create", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-snapshot-create", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
@@ -131,7 +524,7 @@ func makeCmdSnapshotList() *commander.Command {
|
|||||||
UsageLine: "list",
|
UsageLine: "list",
|
||||||
Short: "lists snapshots",
|
Short: "lists snapshots",
|
||||||
Long: `
|
Long: `
|
||||||
list shows full list of snapshots created.
|
Command list shows full list of snapshots created.
|
||||||
|
|
||||||
ex:
|
ex:
|
||||||
$ aptly snapshot list
|
$ aptly snapshot list
|
||||||
@@ -145,13 +538,13 @@ ex:
|
|||||||
func makeCmdSnapshotShow() *commander.Command {
|
func makeCmdSnapshotShow() *commander.Command {
|
||||||
cmd := &commander.Command{
|
cmd := &commander.Command{
|
||||||
Run: aptlySnapshotShow,
|
Run: aptlySnapshotShow,
|
||||||
UsageLine: "show",
|
UsageLine: "show <name>",
|
||||||
Short: "shows details about snapshot",
|
Short: "shows details about snapshot",
|
||||||
Long: `
|
Long: `
|
||||||
shows shows full information about snapshot.
|
Command show displays full information about snapshot.
|
||||||
|
|
||||||
ex:
|
ex.
|
||||||
$ aptly snapshot show <name>
|
$ aptly snapshot show wheezy-main
|
||||||
`,
|
`,
|
||||||
Flag: *flag.NewFlagSet("aptly-snapshot-show", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-snapshot-show", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
@@ -159,6 +552,85 @@ ex:
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeCmdSnapshotVerify() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlySnapshotVerify,
|
||||||
|
UsageLine: "verify <name> [<source> ...]",
|
||||||
|
Short: "verifies that dependencies are satisfied in snapshot",
|
||||||
|
Long: `
|
||||||
|
Verify does depenency resolution in snapshot, possibly using additional snapshots as dependency sources.
|
||||||
|
All unsatisfied dependencies are returned.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly snapshot verify wheezy-main wheezy-contrib wheezy-non-free
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-snapshot-verify", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCmdSnapshotPull() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlySnapshotPull,
|
||||||
|
UsageLine: "pull <name> <source> <destination> <package-name> ...",
|
||||||
|
Short: "performs partial upgrades (pulls new packages) from another snapshot",
|
||||||
|
Long: `
|
||||||
|
Command pull pulls new packages along with its dependencies in <name> snapshot
|
||||||
|
from <source> snapshot. Also can upgrade package version from one snapshot into
|
||||||
|
another, once again along with dependencies. New snapshot <destination> is created as result of this
|
||||||
|
process. Packages could be specified simply as 'package-name' or as dependency 'package-name (>= version)'.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly snapshot pull wheezy-main wheezy-backports wheezy-new-xorg xorg-server-server
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-snapshot-pull", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flag.Bool("dry-run", false, "don't create destination snapshot, just show what would be pulled")
|
||||||
|
cmd.Flag.Bool("no-deps", false, "don't process dependencies, just pull listed packages")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCmdSnapshotDiff() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlySnapshotDiff,
|
||||||
|
UsageLine: "diff <name-a> <name-b>",
|
||||||
|
Short: "calculates difference in packages between two snapshots",
|
||||||
|
Long: `
|
||||||
|
Command diff shows list of missing and new packages, difference in package versions between two snapshots.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly snapshot diff -only-matching wheezy-main wheezy-backports
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-snapshot-diff", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flag.Bool("only-matching", false, "display diff only for matching packages (don't display missing packages)")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCmdSnapshotMerge() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlySnapshotMerge,
|
||||||
|
UsageLine: "merge <destination> <source> [<source>...]",
|
||||||
|
Short: "merges snapshots into one, replacing matching packages",
|
||||||
|
Long: `
|
||||||
|
Merge merges several snapshots into one. Merge happens from left to right. Packages with the same
|
||||||
|
name-architecture pair are replaced during merge (package from latest snapshot on the list wins).
|
||||||
|
If run with only one source snapshot, merge copies source into destination.
|
||||||
|
|
||||||
|
ex.
|
||||||
|
$ aptly snapshot merge wheezy-w-backports wheezy-main wheezy-backports
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-snapshot-merge", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func makeCmdSnapshot() *commander.Command {
|
func makeCmdSnapshot() *commander.Command {
|
||||||
return &commander.Command{
|
return &commander.Command{
|
||||||
UsageLine: "snapshot",
|
UsageLine: "snapshot",
|
||||||
@@ -167,6 +639,10 @@ func makeCmdSnapshot() *commander.Command {
|
|||||||
makeCmdSnapshotCreate(),
|
makeCmdSnapshotCreate(),
|
||||||
makeCmdSnapshotList(),
|
makeCmdSnapshotList(),
|
||||||
makeCmdSnapshotShow(),
|
makeCmdSnapshotShow(),
|
||||||
|
makeCmdSnapshotVerify(),
|
||||||
|
makeCmdSnapshotPull(),
|
||||||
|
makeCmdSnapshotDiff(),
|
||||||
|
makeCmdSnapshotMerge(),
|
||||||
//makeCmdSnapshotDestroy(),
|
//makeCmdSnapshotDestroy(),
|
||||||
},
|
},
|
||||||
Flag: *flag.NewFlagSet("aptly-snapshot", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-snapshot", flag.ExitOnError),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ var (
|
|||||||
type Storage interface {
|
type Storage interface {
|
||||||
Get(key []byte) ([]byte, error)
|
Get(key []byte) ([]byte, error)
|
||||||
Put(key []byte, value []byte) error
|
Put(key []byte, value []byte) error
|
||||||
|
Delete(key []byte) error
|
||||||
FetchByPrefix(prefix []byte) [][]byte
|
FetchByPrefix(prefix []byte) [][]byte
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@@ -60,6 +61,10 @@ func (l *levelDB) Put(key []byte, value []byte) error {
|
|||||||
return l.db.Put(key, value, nil)
|
return l.db.Put(key, value, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *levelDB) Delete(key []byte) error {
|
||||||
|
return l.db.Delete(key, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (l *levelDB) FetchByPrefix(prefix []byte) [][]byte {
|
func (l *levelDB) FetchByPrefix(prefix []byte) [][]byte {
|
||||||
result := make([][]byte, 0, 20)
|
result := make([][]byte, 0, 20)
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,22 @@ func (s *LevelDBSuite) TestGetPut(c *C) {
|
|||||||
c.Assert(result, DeepEquals, value)
|
c.Assert(result, DeepEquals, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *LevelDBSuite) TestDelete(c *C) {
|
||||||
|
var (
|
||||||
|
key = []byte("key")
|
||||||
|
value = []byte("value")
|
||||||
|
)
|
||||||
|
|
||||||
|
err := s.db.Put(key, value)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.db.Delete(key)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
_, err = s.db.Get(key)
|
||||||
|
c.Assert(err, ErrorMatches, "key not found")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *LevelDBSuite) TestFetchByPrefix(c *C) {
|
func (s *LevelDBSuite) TestFetchByPrefix(c *C) {
|
||||||
c.Check(s.db.FetchByPrefix([]byte{0x80}), DeepEquals, [][]byte{})
|
c.Check(s.db.FetchByPrefix([]byte{0x80}), DeepEquals, [][]byte{})
|
||||||
|
|
||||||
|
|||||||
Vendored
+458
-1
@@ -3,23 +3,69 @@ package debian
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Dependency options
|
||||||
|
const (
|
||||||
|
// DepFollowSource pulls source packages when required
|
||||||
|
DepFollowSource = 1 << iota
|
||||||
|
// DepFollowSuggests pulls from suggests
|
||||||
|
DepFollowSuggests
|
||||||
|
// DepFollowRecommends pulls from recommends
|
||||||
|
DepFollowRecommends
|
||||||
|
// DepFollowAllVariants follows all variants if depends on "a | b"
|
||||||
|
DepFollowAllVariants
|
||||||
|
)
|
||||||
|
|
||||||
// PackageList is list of unique (by key) packages
|
// PackageList is list of unique (by key) packages
|
||||||
//
|
//
|
||||||
// It could be seen as repo snapshot, repo contents, result of filtering,
|
// It could be seen as repo snapshot, repo contents, result of filtering,
|
||||||
// merge, etc.
|
// merge, etc.
|
||||||
|
//
|
||||||
|
// If indexed, PackageList starts supporting searching
|
||||||
type PackageList struct {
|
type PackageList struct {
|
||||||
|
// Straight list of packages as map
|
||||||
packages map[string]*Package
|
packages map[string]*Package
|
||||||
|
// Has index been prepared?
|
||||||
|
indexed bool
|
||||||
|
// Indexed list of packages, sorted by name internally
|
||||||
|
packagesIndex []*Package
|
||||||
|
// Map of packages for each virtual package (provides)
|
||||||
|
providesIndex map[string][]*Package
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify interface
|
||||||
|
var (
|
||||||
|
_ sort.Interface = &PackageList{}
|
||||||
|
)
|
||||||
|
|
||||||
// NewPackageList creates empty package list
|
// NewPackageList creates empty package list
|
||||||
func NewPackageList() *PackageList {
|
func NewPackageList() *PackageList {
|
||||||
return &PackageList{packages: make(map[string]*Package, 1000)}
|
return &PackageList{packages: make(map[string]*Package, 1000)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPackageListFromRefList loads packages list from PackageRefList
|
||||||
|
func NewPackageListFromRefList(reflist *PackageRefList, collection *PackageCollection) (*PackageList, error) {
|
||||||
|
result := &PackageList{packages: make(map[string]*Package, reflist.Len())}
|
||||||
|
|
||||||
|
err := reflist.ForEach(func(key []byte) error {
|
||||||
|
p, err := collection.ByKey(key)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load package with key %s: %s", key, err)
|
||||||
|
}
|
||||||
|
return result.Add(p)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Add appends package to package list, additionally checking for uniqueness
|
// Add appends package to package list, additionally checking for uniqueness
|
||||||
func (l *PackageList) Add(p *Package) error {
|
func (l *PackageList) Add(p *Package) error {
|
||||||
key := string(p.Key())
|
key := string(p.Key())
|
||||||
@@ -31,6 +77,19 @@ func (l *PackageList) Add(p *Package) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
l.packages[key] = p
|
l.packages[key] = p
|
||||||
|
|
||||||
|
if l.indexed {
|
||||||
|
for _, provides := range p.Provides {
|
||||||
|
l.providesIndex[provides] = append(l.providesIndex[provides], p)
|
||||||
|
}
|
||||||
|
|
||||||
|
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name })
|
||||||
|
|
||||||
|
// insert p into l.packagesIndex in position i
|
||||||
|
l.packagesIndex = append(l.packagesIndex, nil)
|
||||||
|
copy(l.packagesIndex[i+1:], l.packagesIndex[i:])
|
||||||
|
l.packagesIndex[i] = p
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,15 +110,253 @@ func (l *PackageList) Len() int {
|
|||||||
return len(l.packages)
|
return len(l.packages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append adds content from one package list to another
|
||||||
|
func (l *PackageList) Append(pl *PackageList) error {
|
||||||
|
if l.indexed {
|
||||||
|
panic("Append not supported when indexed")
|
||||||
|
}
|
||||||
|
for k, p := range pl.packages {
|
||||||
|
existing, ok := l.packages[k]
|
||||||
|
if ok {
|
||||||
|
if !existing.Equals(p) {
|
||||||
|
return fmt.Errorf("conflict in package %s: %#v != %#v", p, existing, p)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l.packages[k] = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes package from the list, and updates index when required
|
||||||
|
func (l *PackageList) Remove(p *Package) {
|
||||||
|
delete(l.packages, string(p.Key()))
|
||||||
|
if l.indexed {
|
||||||
|
for _, provides := range p.Provides {
|
||||||
|
for i, pkg := range l.providesIndex[provides] {
|
||||||
|
if pkg.Equals(p) {
|
||||||
|
// remove l.ProvidesIndex[provides][i] w/o preserving order
|
||||||
|
l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][i], l.providesIndex[provides] =
|
||||||
|
nil, l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][:len(l.providesIndex[provides])-1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name })
|
||||||
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == p.Name {
|
||||||
|
if l.packagesIndex[i].Equals(p) {
|
||||||
|
// remove l.packagesIndex[i] preserving order
|
||||||
|
copy(l.packagesIndex[i:], l.packagesIndex[i+1:])
|
||||||
|
l.packagesIndex[len(l.packagesIndex)-1] = nil
|
||||||
|
l.packagesIndex = l.packagesIndex[:len(l.packagesIndex)-1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Architectures returns list of architectures present in packages
|
||||||
|
func (l *PackageList) Architectures() (result []string) {
|
||||||
|
result = make([]string, 0, 10)
|
||||||
|
for _, pkg := range l.packages {
|
||||||
|
if pkg.Architecture != "all" && !utils.StrSliceHasItem(result, pkg.Architecture) {
|
||||||
|
result = append(result, pkg.Architecture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// depSliceDeduplicate removes dups in slice of Dependencies
|
||||||
|
func depSliceDeduplicate(s []Dependency) []Dependency {
|
||||||
|
l := len(s)
|
||||||
|
if l < 2 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if l == 2 {
|
||||||
|
if s[0] == s[1] {
|
||||||
|
return s[0:1]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
found := make(map[string]bool, l)
|
||||||
|
j := 0
|
||||||
|
for i, x := range s {
|
||||||
|
h := x.Hash()
|
||||||
|
if !found[h] {
|
||||||
|
found[h] = true
|
||||||
|
s[j] = s[i]
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s[:j]
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyDependencies looks for missing dependencies in package list.
|
||||||
|
//
|
||||||
|
// Analysis would be peformed for each architecture, in specified sources
|
||||||
|
func (l *PackageList) VerifyDependencies(options int, architectures []string, sources *PackageList) ([]Dependency, error) {
|
||||||
|
missing := make([]Dependency, 0, 128)
|
||||||
|
|
||||||
|
for _, arch := range architectures {
|
||||||
|
cache := make(map[string]bool, 2048)
|
||||||
|
|
||||||
|
for _, p := range l.packages {
|
||||||
|
if !p.MatchesArchitecture(arch) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dep := range p.GetDependencies(options) {
|
||||||
|
variants, err := ParseDependencyVariants(dep)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to process package %s: %s", p, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
variants = depSliceDeduplicate(variants)
|
||||||
|
|
||||||
|
variantsMissing := make([]Dependency, 0, len(variants))
|
||||||
|
missingCount := 0
|
||||||
|
|
||||||
|
for _, dep := range variants {
|
||||||
|
dep.Architecture = arch
|
||||||
|
|
||||||
|
hash := dep.Hash()
|
||||||
|
r, ok := cache[hash]
|
||||||
|
if ok {
|
||||||
|
if !r {
|
||||||
|
missingCount++
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if sources.Search(dep) == nil {
|
||||||
|
variantsMissing = append(variantsMissing, dep)
|
||||||
|
missingCount++
|
||||||
|
} else {
|
||||||
|
cache[hash] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options&DepFollowAllVariants == DepFollowAllVariants {
|
||||||
|
missing = append(missing, variantsMissing...)
|
||||||
|
for _, dep := range variantsMissing {
|
||||||
|
cache[dep.Hash()] = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if missingCount == len(variants) {
|
||||||
|
missing = append(missing, variantsMissing...)
|
||||||
|
for _, dep := range variantsMissing {
|
||||||
|
cache[dep.Hash()] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return missing, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps two packages in index
|
||||||
|
func (l *PackageList) Swap(i, j int) {
|
||||||
|
l.packagesIndex[i], l.packagesIndex[j] = l.packagesIndex[j], l.packagesIndex[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare compares two names in lexographical order
|
||||||
|
func (l *PackageList) Less(i, j int) bool {
|
||||||
|
return l.packagesIndex[i].Name < l.packagesIndex[j].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareIndex prepares list for indexing
|
||||||
|
func (l *PackageList) PrepareIndex() {
|
||||||
|
l.packagesIndex = make([]*Package, l.Len())
|
||||||
|
l.providesIndex = make(map[string][]*Package, 128)
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, p := range l.packages {
|
||||||
|
l.packagesIndex[i] = p
|
||||||
|
i++
|
||||||
|
|
||||||
|
for _, provides := range p.Provides {
|
||||||
|
l.providesIndex[provides] = append(l.providesIndex[provides], p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(l)
|
||||||
|
|
||||||
|
l.indexed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search searches package index for specified package
|
||||||
|
func (l *PackageList) Search(dep Dependency) *Package {
|
||||||
|
if !l.indexed {
|
||||||
|
panic("list not indexed, can't search")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dep.Relation == VersionDontCare {
|
||||||
|
for _, p := range l.providesIndex[dep.Pkg] {
|
||||||
|
if p.MatchesArchitecture(dep.Architecture) {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg })
|
||||||
|
|
||||||
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
||||||
|
p := l.packagesIndex[i]
|
||||||
|
if p.MatchesArchitecture(dep.Architecture) {
|
||||||
|
if dep.Relation == VersionDontCare {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
r := CompareVersions(p.Version, dep.Version)
|
||||||
|
switch dep.Relation {
|
||||||
|
case VersionEqual:
|
||||||
|
if r == 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
case VersionLess:
|
||||||
|
if r < 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
case VersionGreater:
|
||||||
|
if r > 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
case VersionLessOrEqual:
|
||||||
|
if r <= 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
case VersionGreaterOrEqual:
|
||||||
|
if r >= 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PackageRefList is a list of keys of packages, this is basis for snapshot
|
// PackageRefList is a list of keys of packages, this is basis for snapshot
|
||||||
// and similar stuff
|
// and similar stuff
|
||||||
//
|
//
|
||||||
// Refs are sorted in lexographical order
|
// Refs are sorted in lexicographical order
|
||||||
type PackageRefList struct {
|
type PackageRefList struct {
|
||||||
// List of package keys
|
// List of package keys
|
||||||
Refs [][]byte
|
Refs [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify interface
|
||||||
|
var (
|
||||||
|
_ sort.Interface = &PackageRefList{}
|
||||||
|
)
|
||||||
|
|
||||||
// NewPackageRefListFromPackageList creates PackageRefList from PackageList
|
// NewPackageRefListFromPackageList creates PackageRefList from PackageList
|
||||||
func NewPackageRefListFromPackageList(list *PackageList) *PackageRefList {
|
func NewPackageRefListFromPackageList(list *PackageList) *PackageRefList {
|
||||||
reflist := &PackageRefList{}
|
reflist := &PackageRefList{}
|
||||||
@@ -118,3 +415,163 @@ func (l *PackageRefList) ForEach(handler func([]byte) error) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PackageDiff is a difference between two packages in a list.
|
||||||
|
//
|
||||||
|
// If left & right are present, difference is in package version
|
||||||
|
// If left is nil, package is present only in right
|
||||||
|
// If right is nil, package is present only in left
|
||||||
|
type PackageDiff struct {
|
||||||
|
Left, Right *Package
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageDiffs is a list of PackageDiff records
|
||||||
|
type PackageDiffs []PackageDiff
|
||||||
|
|
||||||
|
// Diff calculates difference between two reflists
|
||||||
|
func (l *PackageRefList) Diff(r *PackageRefList, packageCollection *PackageCollection) (result PackageDiffs, err error) {
|
||||||
|
result = make(PackageDiffs, 0, 128)
|
||||||
|
|
||||||
|
// pointer to left and right reflists
|
||||||
|
il, ir := 0, 0
|
||||||
|
// length of reflists
|
||||||
|
ll, lr := l.Len(), r.Len()
|
||||||
|
// cached loaded packages on the left & right
|
||||||
|
pl, pr := (*Package)(nil), (*Package)(nil)
|
||||||
|
|
||||||
|
// until we reached end of both lists
|
||||||
|
for il < ll || ir < lr {
|
||||||
|
// if we've exhausted left list, pull the rest from the right
|
||||||
|
if il == ll {
|
||||||
|
pr, err = packageCollection.ByKey(r.Refs[ir])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, PackageDiff{Left: nil, Right: pr})
|
||||||
|
ir++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// if we've exhausted right list, pull the rest from the left
|
||||||
|
if ir == lr {
|
||||||
|
pl, err = packageCollection.ByKey(l.Refs[il])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: nil})
|
||||||
|
il++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// refs on both sides are present, load them
|
||||||
|
rl, rr := l.Refs[il], r.Refs[ir]
|
||||||
|
// compare refs
|
||||||
|
rel := bytes.Compare(rl, rr)
|
||||||
|
|
||||||
|
if rel == 0 {
|
||||||
|
// refs are identical, so are packages, advance pointer
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
pl, pr = nil, nil
|
||||||
|
} else {
|
||||||
|
// load pl & pr if they haven't been loaded before
|
||||||
|
if pl == nil {
|
||||||
|
pl, err = packageCollection.ByKey(rl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pr == nil {
|
||||||
|
pr, err = packageCollection.ByKey(rr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is pl & pr the same package, but different version?
|
||||||
|
if pl.Name == pr.Name && pl.Architecture == pr.Architecture {
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: pr})
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
pl, pr = nil, nil
|
||||||
|
} else {
|
||||||
|
// otherwise pl or pr is missing on one of the sides
|
||||||
|
if rel < 0 {
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: nil})
|
||||||
|
il++
|
||||||
|
pl = nil
|
||||||
|
} else {
|
||||||
|
result = append(result, PackageDiff{Left: nil, Right: pr})
|
||||||
|
ir++
|
||||||
|
pr = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges reflist r into current reflist. Merge replaces matching packages (by architecture/name)
|
||||||
|
// with reference from r.
|
||||||
|
func (l *PackageRefList) Merge(r *PackageRefList) (result *PackageRefList) {
|
||||||
|
// pointer to left and right reflists
|
||||||
|
il, ir := 0, 0
|
||||||
|
// length of reflists
|
||||||
|
ll, lr := l.Len(), r.Len()
|
||||||
|
|
||||||
|
result = &PackageRefList{}
|
||||||
|
result.Refs = make([][]byte, 0, ll+lr)
|
||||||
|
|
||||||
|
// until we reached end of both lists
|
||||||
|
for il < ll || ir < lr {
|
||||||
|
// if we've exhausted left list, pull the rest from the right
|
||||||
|
if il == ll {
|
||||||
|
result.Refs = append(result.Refs, r.Refs[ir:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// if we've exhausted right list, pull the rest from the left
|
||||||
|
if ir == lr {
|
||||||
|
result.Refs = append(result.Refs, l.Refs[il:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// refs on both sides are present, load them
|
||||||
|
rl, rr := l.Refs[il], r.Refs[ir]
|
||||||
|
// compare refs
|
||||||
|
rel := bytes.Compare(rl, rr)
|
||||||
|
|
||||||
|
if rel == 0 {
|
||||||
|
// refs are identical, so are packages, advance pointer
|
||||||
|
result.Refs = append(result.Refs, l.Refs[il])
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
} else {
|
||||||
|
partsL := bytes.Split(rl, []byte(" "))
|
||||||
|
archL, nameL := partsL[0][1:], partsL[1]
|
||||||
|
|
||||||
|
partsR := bytes.Split(rr, []byte(" "))
|
||||||
|
archR, nameR := partsR[0][1:], partsR[1]
|
||||||
|
|
||||||
|
if bytes.Compare(archL, archR) == 0 && bytes.Compare(nameL, nameR) == 0 {
|
||||||
|
// override with package from the right
|
||||||
|
result.Refs = append(result.Refs, r.Refs[ir])
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
} else {
|
||||||
|
// otherwise append smallest of two
|
||||||
|
if rel < 0 {
|
||||||
|
result.Refs = append(result.Refs, l.Refs[il])
|
||||||
|
il++
|
||||||
|
} else {
|
||||||
|
result.Refs = append(result.Refs, r.Refs[ir])
|
||||||
|
ir++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+328
@@ -2,12 +2,19 @@ package debian
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
. "launchpad.net/gocheck"
|
. "launchpad.net/gocheck"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PackageListSuite struct {
|
type PackageListSuite struct {
|
||||||
|
// Simple list with "real" packages from stanzas
|
||||||
list *PackageList
|
list *PackageList
|
||||||
p1, p2, p3, p4, p5, p6 *Package
|
p1, p2, p3, p4, p5, p6 *Package
|
||||||
|
|
||||||
|
// Mocked packages in list
|
||||||
|
packages []*Package
|
||||||
|
il *PackageList
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&PackageListSuite{})
|
var _ = Suite(&PackageListSuite{})
|
||||||
@@ -29,6 +36,27 @@ func (s *PackageListSuite) SetUpTest(c *C) {
|
|||||||
stanza = packageStanza.Copy()
|
stanza = packageStanza.Copy()
|
||||||
stanza["Version"] = "99.1"
|
stanza["Version"] = "99.1"
|
||||||
s.p6 = NewPackageFromControlFile(stanza)
|
s.p6 = NewPackageFromControlFile(stanza)
|
||||||
|
|
||||||
|
s.il = NewPackageList()
|
||||||
|
s.packages = []*Package{
|
||||||
|
&Package{Name: "lib", Version: "1.0", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"mail-agent"}},
|
||||||
|
&Package{Name: "dpkg", Version: "1.7", Architecture: "i386", Provides: []string{"package-installer"}},
|
||||||
|
&Package{Name: "data", Version: "1.1~bp1", Architecture: "all", PreDepends: []string{"dpkg (>= 1.6)"}},
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}},
|
||||||
|
&Package{Name: "mailer", Version: "3.5.8", Architecture: "i386", Provides: []string{"mail-agent"}},
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "amd64", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}},
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}},
|
||||||
|
&Package{Name: "app", Version: "1.0", Architecture: "s390", PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}},
|
||||||
|
&Package{Name: "aa", Version: "2.0-1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}},
|
||||||
|
&Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "amd64", Provides: []string{"package-installer"}},
|
||||||
|
&Package{Name: "libx", Version: "1.5", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}},
|
||||||
|
&Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "arm", Provides: []string{"package-installer"}},
|
||||||
|
}
|
||||||
|
for _, p := range s.packages {
|
||||||
|
s.il.Add(p)
|
||||||
|
}
|
||||||
|
s.il.PrepareIndex()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageListSuite) TestAddLen(c *C) {
|
func (s *PackageListSuite) TestAddLen(c *C) {
|
||||||
@@ -42,6 +70,73 @@ func (s *PackageListSuite) TestAddLen(c *C) {
|
|||||||
c.Check(s.list.Add(s.p4), ErrorMatches, "conflict in package.*")
|
c.Check(s.list.Add(s.p4), ErrorMatches, "conflict in package.*")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestRemove(c *C) {
|
||||||
|
c.Check(s.list.Add(s.p1), IsNil)
|
||||||
|
c.Check(s.list.Add(s.p3), IsNil)
|
||||||
|
c.Check(s.list.Len(), Equals, 2)
|
||||||
|
|
||||||
|
s.list.Remove(s.p1)
|
||||||
|
c.Check(s.list.Len(), Equals, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestAddWhenIndexed(c *C) {
|
||||||
|
c.Check(s.list.Len(), Equals, 0)
|
||||||
|
s.list.PrepareIndex()
|
||||||
|
|
||||||
|
c.Check(s.list.Add(&Package{Name: "a1st", Version: "1.0", Architecture: "i386", Provides: []string{"fa", "fb"}}), IsNil)
|
||||||
|
c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
|
||||||
|
|
||||||
|
c.Check(s.list.Add(&Package{Name: "c3rd", Version: "1.0", Architecture: "i386", Provides: []string{"fa"}}), IsNil)
|
||||||
|
c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.packagesIndex[1].Name, Equals, "c3rd")
|
||||||
|
c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd")
|
||||||
|
c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
|
||||||
|
|
||||||
|
c.Check(s.list.Add(&Package{Name: "b2nd", Version: "1.0", Architecture: "i386"}), IsNil)
|
||||||
|
c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.packagesIndex[1].Name, Equals, "b2nd")
|
||||||
|
c.Check(s.list.packagesIndex[2].Name, Equals, "c3rd")
|
||||||
|
c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
|
||||||
|
c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd")
|
||||||
|
c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestRemoveWhenIndexed(c *C) {
|
||||||
|
s.il.Remove(s.packages[0])
|
||||||
|
names := make([]string, s.il.Len())
|
||||||
|
for i, p := range s.il.packagesIndex {
|
||||||
|
names[i] = p.Name
|
||||||
|
}
|
||||||
|
c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "libx", "mailer"})
|
||||||
|
|
||||||
|
s.il.Remove(s.packages[4])
|
||||||
|
names = make([]string, s.il.Len())
|
||||||
|
for i, p := range s.il.packagesIndex {
|
||||||
|
names[i] = p.Name
|
||||||
|
}
|
||||||
|
c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "libx"})
|
||||||
|
c.Check(s.il.providesIndex["mail-agent"], DeepEquals, []*Package{})
|
||||||
|
|
||||||
|
s.il.Remove(s.packages[9])
|
||||||
|
names = make([]string, s.il.Len())
|
||||||
|
for i, p := range s.il.packagesIndex {
|
||||||
|
names[i] = p.Name
|
||||||
|
}
|
||||||
|
c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "libx"})
|
||||||
|
c.Check(s.il.providesIndex["package-installer"], HasLen, 2)
|
||||||
|
|
||||||
|
s.il.Remove(s.packages[1])
|
||||||
|
names = make([]string, s.il.Len())
|
||||||
|
for i, p := range s.il.packagesIndex {
|
||||||
|
names[i] = p.Name
|
||||||
|
}
|
||||||
|
c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "libx"})
|
||||||
|
c.Check(s.il.providesIndex["package-installer"], DeepEquals, []*Package{s.packages[11]})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PackageListSuite) TestForeach(c *C) {
|
func (s *PackageListSuite) TestForeach(c *C) {
|
||||||
s.list.Add(s.p1)
|
s.list.Add(s.p1)
|
||||||
s.list.Add(s.p3)
|
s.list.Add(s.p3)
|
||||||
@@ -65,6 +160,114 @@ func (s *PackageListSuite) TestForeach(c *C) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestIndex(c *C) {
|
||||||
|
c.Check(len(s.il.providesIndex), Equals, 2)
|
||||||
|
c.Check(len(s.il.providesIndex["mail-agent"]), Equals, 1)
|
||||||
|
c.Check(len(s.il.providesIndex["package-installer"]), Equals, 3)
|
||||||
|
c.Check(s.il.packagesIndex[0], Equals, s.packages[8])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestAppend(c *C) {
|
||||||
|
s.list.Add(s.p1)
|
||||||
|
s.list.Add(s.p3)
|
||||||
|
|
||||||
|
err := s.list.Append(s.il)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(s.list.Len(), Equals, 14)
|
||||||
|
|
||||||
|
list := NewPackageList()
|
||||||
|
list.Add(s.p4)
|
||||||
|
|
||||||
|
err = s.list.Append(list)
|
||||||
|
c.Check(err, ErrorMatches, "conflict.*")
|
||||||
|
|
||||||
|
s.list.PrepareIndex()
|
||||||
|
c.Check(func() { s.list.Append(s.il) }, Panics, "Append not supported when indexed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestSearch(c *C) {
|
||||||
|
c.Check(func() { s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}) }, Panics, "list not indexed, can't search")
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "mail-agent"}), Equals, s.packages[4])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "puppy"}), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp1"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp2"}), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1~~"}), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~~"}), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.0"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.2"}), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3])
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}), IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestVerifyDependencies(c *C) {
|
||||||
|
missing, err := s.il.VerifyDependencies(0, []string{"i386"}, s.il)
|
||||||
|
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(missing, DeepEquals, []Dependency{})
|
||||||
|
|
||||||
|
missing, err = s.il.VerifyDependencies(0, []string{"i386", "amd64"}, s.il)
|
||||||
|
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "amd64"}})
|
||||||
|
|
||||||
|
missing, err = s.il.VerifyDependencies(0, []string{"arm"}, s.il)
|
||||||
|
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(missing, DeepEquals, []Dependency{})
|
||||||
|
|
||||||
|
missing, err = s.il.VerifyDependencies(DepFollowAllVariants, []string{"arm"}, s.il)
|
||||||
|
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "arm"},
|
||||||
|
Dependency{Pkg: "mail-agent", Relation: VersionDontCare, Version: "", Architecture: "arm"}})
|
||||||
|
|
||||||
|
_, err = s.il.VerifyDependencies(0, []string{"i386", "amd64", "s390"}, s.il)
|
||||||
|
|
||||||
|
c.Check(err, ErrorMatches, "unable to process package app-1.0_s390:.*")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestArchitectures(c *C) {
|
||||||
|
archs := s.il.Architectures()
|
||||||
|
sort.Strings(archs)
|
||||||
|
c.Check(archs, DeepEquals, []string{"amd64", "arm", "i386", "s390"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestNewPackageListFromRefList(c *C) {
|
||||||
|
db, _ := database.OpenDB(c.MkDir())
|
||||||
|
coll := NewPackageCollection(db)
|
||||||
|
coll.Update(s.p1)
|
||||||
|
coll.Update(s.p3)
|
||||||
|
|
||||||
|
s.list.Add(s.p1)
|
||||||
|
s.list.Add(s.p3)
|
||||||
|
s.list.Add(s.p5)
|
||||||
|
s.list.Add(s.p6)
|
||||||
|
|
||||||
|
reflist := NewPackageRefListFromPackageList(s.list)
|
||||||
|
|
||||||
|
_, err := NewPackageListFromRefList(reflist, coll)
|
||||||
|
c.Assert(err, ErrorMatches, "unable to load package with key.*")
|
||||||
|
|
||||||
|
coll.Update(s.p5)
|
||||||
|
coll.Update(s.p6)
|
||||||
|
|
||||||
|
list, err := NewPackageListFromRefList(reflist, coll)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Check(list.Len(), Equals, 4)
|
||||||
|
c.Check(list.Add(s.p4), ErrorMatches, "conflict in package.*")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PackageListSuite) TestNewPackageRefList(c *C) {
|
func (s *PackageListSuite) TestNewPackageRefList(c *C) {
|
||||||
s.list.Add(s.p1)
|
s.list.Add(s.p1)
|
||||||
s.list.Add(s.p3)
|
s.list.Add(s.p3)
|
||||||
@@ -119,3 +322,128 @@ func (s *PackageListSuite) TestPackageRefListForeach(c *C) {
|
|||||||
|
|
||||||
c.Check(err, Equals, e)
|
c.Check(err, Equals, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestDiff(c *C) {
|
||||||
|
db, _ := database.OpenDB(c.MkDir())
|
||||||
|
coll := NewPackageCollection(db)
|
||||||
|
|
||||||
|
packages := []*Package{
|
||||||
|
&Package{Name: "lib", Version: "1.0", Architecture: "i386"}, //0
|
||||||
|
&Package{Name: "dpkg", Version: "1.7", Architecture: "i386"}, //1
|
||||||
|
&Package{Name: "data", Version: "1.1~bp1", Architecture: "all"}, //2
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "i386"}, //3
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "i386"}, //4
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "amd64"}, //5
|
||||||
|
&Package{Name: "xyz", Version: "3.0", Architecture: "sparc"}, //6
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range packages {
|
||||||
|
coll.Update(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
listA := NewPackageList()
|
||||||
|
listA.Add(packages[0])
|
||||||
|
listA.Add(packages[1])
|
||||||
|
listA.Add(packages[2])
|
||||||
|
listA.Add(packages[3])
|
||||||
|
listA.Add(packages[6])
|
||||||
|
|
||||||
|
listB := NewPackageList()
|
||||||
|
listB.Add(packages[0])
|
||||||
|
listB.Add(packages[2])
|
||||||
|
listB.Add(packages[4])
|
||||||
|
listB.Add(packages[5])
|
||||||
|
|
||||||
|
reflistA := NewPackageRefListFromPackageList(listA)
|
||||||
|
reflistB := NewPackageRefListFromPackageList(listB)
|
||||||
|
|
||||||
|
diffAA, err := reflistA.Diff(reflistA, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(diffAA, HasLen, 0)
|
||||||
|
|
||||||
|
diffAB, err := reflistA.Diff(reflistB, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(diffAB, HasLen, 4)
|
||||||
|
|
||||||
|
c.Check(diffAB[0].Left, IsNil)
|
||||||
|
c.Check(diffAB[0].Right.String(), Equals, "app-1.1~bp2_amd64")
|
||||||
|
|
||||||
|
c.Check(diffAB[1].Left.String(), Equals, "app-1.1~bp1_i386")
|
||||||
|
c.Check(diffAB[1].Right.String(), Equals, "app-1.1~bp2_i386")
|
||||||
|
|
||||||
|
c.Check(diffAB[2].Left.String(), Equals, "dpkg-1.7_i386")
|
||||||
|
c.Check(diffAB[2].Right, IsNil)
|
||||||
|
|
||||||
|
c.Check(diffAB[3].Left.String(), Equals, "xyz-3.0_sparc")
|
||||||
|
c.Check(diffAB[3].Right, IsNil)
|
||||||
|
|
||||||
|
diffBA, err := reflistB.Diff(reflistA, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(diffBA, HasLen, 4)
|
||||||
|
|
||||||
|
c.Check(diffBA[0].Right, IsNil)
|
||||||
|
c.Check(diffBA[0].Left.String(), Equals, "app-1.1~bp2_amd64")
|
||||||
|
|
||||||
|
c.Check(diffBA[1].Right.String(), Equals, "app-1.1~bp1_i386")
|
||||||
|
c.Check(diffBA[1].Left.String(), Equals, "app-1.1~bp2_i386")
|
||||||
|
|
||||||
|
c.Check(diffBA[2].Right.String(), Equals, "dpkg-1.7_i386")
|
||||||
|
c.Check(diffBA[2].Left, IsNil)
|
||||||
|
|
||||||
|
c.Check(diffBA[3].Right.String(), Equals, "xyz-3.0_sparc")
|
||||||
|
c.Check(diffBA[3].Left, IsNil)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestMerge(c *C) {
|
||||||
|
db, _ := database.OpenDB(c.MkDir())
|
||||||
|
coll := NewPackageCollection(db)
|
||||||
|
|
||||||
|
packages := []*Package{
|
||||||
|
&Package{Name: "lib", Version: "1.0", Architecture: "i386"}, //0
|
||||||
|
&Package{Name: "dpkg", Version: "1.7", Architecture: "i386"}, //1
|
||||||
|
&Package{Name: "data", Version: "1.1~bp1", Architecture: "all"}, //2
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "i386"}, //3
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "i386"}, //4
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "amd64"}, //5
|
||||||
|
&Package{Name: "dpkg", Version: "1.0", Architecture: "i386"}, //6
|
||||||
|
&Package{Name: "xyz", Version: "1.0", Architecture: "sparc"}, //7
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range packages {
|
||||||
|
coll.Update(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
listA := NewPackageList()
|
||||||
|
listA.Add(packages[0])
|
||||||
|
listA.Add(packages[1])
|
||||||
|
listA.Add(packages[2])
|
||||||
|
listA.Add(packages[3])
|
||||||
|
listA.Add(packages[7])
|
||||||
|
|
||||||
|
listB := NewPackageList()
|
||||||
|
listB.Add(packages[0])
|
||||||
|
listB.Add(packages[2])
|
||||||
|
listB.Add(packages[4])
|
||||||
|
listB.Add(packages[5])
|
||||||
|
listB.Add(packages[6])
|
||||||
|
|
||||||
|
reflistA := NewPackageRefListFromPackageList(listA)
|
||||||
|
reflistB := NewPackageRefListFromPackageList(listB)
|
||||||
|
|
||||||
|
mergeAB := reflistA.Merge(reflistB)
|
||||||
|
mergeBA := reflistB.Merge(reflistA)
|
||||||
|
|
||||||
|
toStrSlice := func(reflist *PackageRefList) (result []string) {
|
||||||
|
result = make([]string, reflist.Len())
|
||||||
|
for i, r := range reflist.Refs {
|
||||||
|
result[i] = string(r)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Check(toStrSlice(mergeAB), DeepEquals,
|
||||||
|
[]string{"Pall data 1.1~bp1", "Pamd64 app 1.1~bp2", "Pi386 app 1.1~bp2", "Pi386 dpkg 1.0", "Pi386 lib 1.0", "Psparc xyz 1.0"})
|
||||||
|
c.Check(toStrSlice(mergeBA), DeepEquals,
|
||||||
|
[]string{"Pall data 1.1~bp1", "Pamd64 app 1.1~bp2", "Pi386 app 1.1~bp1", "Pi386 dpkg 1.7", "Pi386 lib 1.0", "Psparc xyz 1.0"})
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+185
-33
@@ -7,29 +7,48 @@ import (
|
|||||||
"github.com/smira/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PackageFile is a single file entry in package
|
||||||
|
type PackageFile struct {
|
||||||
|
Filename string
|
||||||
|
Checksums utils.ChecksumInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that package file is present and correct
|
||||||
|
func (f *PackageFile) Verify(packageRepo *Repository) (bool, error) {
|
||||||
|
poolPath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
st, err := os.Stat(poolPath)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify size
|
||||||
|
// TODO: verify checksum if configured
|
||||||
|
return st.Size() == f.Checksums.Size, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Package is single instance of Debian package
|
// Package is single instance of Debian package
|
||||||
//
|
|
||||||
// TODO: support source & binary
|
|
||||||
type Package struct {
|
type Package struct {
|
||||||
Name string
|
Name string
|
||||||
Version string
|
Version string
|
||||||
Filename string
|
|
||||||
Filesize int64
|
|
||||||
Architecture string
|
Architecture string
|
||||||
Source string
|
Source string
|
||||||
|
Provides []string
|
||||||
// Various dependencies
|
// Various dependencies
|
||||||
Depends []string
|
Depends []string
|
||||||
PreDepends []string
|
PreDepends []string
|
||||||
Suggests []string
|
Suggests []string
|
||||||
Recommends []string
|
Recommends []string
|
||||||
// Hashsums of package contents
|
// Files in package
|
||||||
HashMD5 string
|
Files []PackageFile
|
||||||
HashSHA1 string
|
|
||||||
HashSHA256 string
|
|
||||||
// Extra information from stanza
|
// Extra information from stanza
|
||||||
Extra Stanza
|
Extra Stanza
|
||||||
}
|
}
|
||||||
@@ -42,7 +61,11 @@ func parseDependencies(input Stanza, key string) []string {
|
|||||||
|
|
||||||
delete(input, key)
|
delete(input, key)
|
||||||
|
|
||||||
return strings.Split(value, ", ")
|
result := strings.Split(value, ",")
|
||||||
|
for i := range result {
|
||||||
|
result[i] = strings.TrimSpace(result[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPackageFromControlFile creates Package from parsed Debian control file
|
// NewPackageFromControlFile creates Package from parsed Debian control file
|
||||||
@@ -50,30 +73,39 @@ func NewPackageFromControlFile(input Stanza) *Package {
|
|||||||
result := &Package{
|
result := &Package{
|
||||||
Name: input["Package"],
|
Name: input["Package"],
|
||||||
Version: input["Version"],
|
Version: input["Version"],
|
||||||
Filename: input["Filename"],
|
|
||||||
Architecture: input["Architecture"],
|
Architecture: input["Architecture"],
|
||||||
Source: input["Source"],
|
Source: input["Source"],
|
||||||
HashMD5: input["MD5sum"],
|
Files: make([]PackageFile, 0, 1),
|
||||||
HashSHA1: input["SHA1"],
|
|
||||||
HashSHA256: input["SHA256"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(input, "Package")
|
delete(input, "Package")
|
||||||
delete(input, "Version")
|
delete(input, "Version")
|
||||||
delete(input, "Filename")
|
|
||||||
delete(input, "Architecture")
|
delete(input, "Architecture")
|
||||||
delete(input, "Source")
|
delete(input, "Source")
|
||||||
|
|
||||||
|
filesize, _ := strconv.ParseInt(input["Size"], 10, 64)
|
||||||
|
|
||||||
|
result.Files = append(result.Files, PackageFile{
|
||||||
|
Filename: input["Filename"],
|
||||||
|
Checksums: utils.ChecksumInfo{
|
||||||
|
Size: filesize,
|
||||||
|
MD5: input["MD5sum"],
|
||||||
|
SHA1: input["SHA1"],
|
||||||
|
SHA256: input["SHA256"],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
delete(input, "Filename")
|
||||||
delete(input, "MD5sum")
|
delete(input, "MD5sum")
|
||||||
delete(input, "SHA1")
|
delete(input, "SHA1")
|
||||||
delete(input, "SHA256")
|
delete(input, "SHA256")
|
||||||
|
|
||||||
result.Filesize, _ = strconv.ParseInt(input["Size"], 10, 64)
|
|
||||||
delete(input, "Size")
|
delete(input, "Size")
|
||||||
|
|
||||||
result.Depends = parseDependencies(input, "Depends")
|
result.Depends = parseDependencies(input, "Depends")
|
||||||
result.PreDepends = parseDependencies(input, "Pre-Depends")
|
result.PreDepends = parseDependencies(input, "Pre-Depends")
|
||||||
result.Suggests = parseDependencies(input, "Suggests")
|
result.Suggests = parseDependencies(input, "Suggests")
|
||||||
result.Recommends = parseDependencies(input, "Recommends")
|
result.Recommends = parseDependencies(input, "Recommends")
|
||||||
|
result.Provides = parseDependencies(input, "Provides")
|
||||||
|
|
||||||
result.Extra = input
|
result.Extra = input
|
||||||
|
|
||||||
@@ -82,7 +114,7 @@ func NewPackageFromControlFile(input Stanza) *Package {
|
|||||||
|
|
||||||
// Key returns unique key identifying package
|
// Key returns unique key identifying package
|
||||||
func (p *Package) Key() []byte {
|
func (p *Package) Key() []byte {
|
||||||
return []byte("P" + p.Name + " " + p.Version + " " + p.Architecture)
|
return []byte("P" + p.Architecture + " " + p.Name + " " + p.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode does msgpack encoding of Package
|
// Encode does msgpack encoding of Package
|
||||||
@@ -106,23 +138,49 @@ func (p *Package) String() string {
|
|||||||
return fmt.Sprintf("%s-%s_%s", p.Name, p.Version, p.Architecture)
|
return fmt.Sprintf("%s-%s_%s", p.Name, p.Version, p.Architecture)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchesArchitecture checks whether packages matches specified architecture
|
||||||
|
func (p *Package) MatchesArchitecture(arch string) bool {
|
||||||
|
if p.Architecture == "all" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Architecture == arch
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDependencies compiles list of dependenices by flags from options
|
||||||
|
func (p *Package) GetDependencies(options int) (dependencies []string) {
|
||||||
|
dependencies = make([]string, 0, 30)
|
||||||
|
dependencies = append(dependencies, p.Depends...)
|
||||||
|
dependencies = append(dependencies, p.PreDepends...)
|
||||||
|
|
||||||
|
if options&DepFollowRecommends == DepFollowRecommends {
|
||||||
|
dependencies = append(dependencies, p.Recommends...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if options&DepFollowSuggests == DepFollowSuggests {
|
||||||
|
dependencies = append(dependencies, p.Suggests...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Stanza creates original stanza from package
|
// Stanza creates original stanza from package
|
||||||
func (p *Package) Stanza() (result Stanza) {
|
func (p *Package) Stanza() (result Stanza) {
|
||||||
result = p.Extra.Copy()
|
result = p.Extra.Copy()
|
||||||
result["Package"] = p.Name
|
result["Package"] = p.Name
|
||||||
result["Version"] = p.Version
|
result["Version"] = p.Version
|
||||||
result["Filename"] = p.Filename
|
result["Filename"] = p.Files[0].Filename
|
||||||
result["Architecture"] = p.Architecture
|
result["Architecture"] = p.Architecture
|
||||||
result["Source"] = p.Source
|
result["Source"] = p.Source
|
||||||
|
|
||||||
if p.HashMD5 != "" {
|
if p.Files[0].Checksums.MD5 != "" {
|
||||||
result["MD5sum"] = p.HashMD5
|
result["MD5sum"] = p.Files[0].Checksums.MD5
|
||||||
}
|
}
|
||||||
if p.HashSHA1 != "" {
|
if p.Files[0].Checksums.SHA1 != "" {
|
||||||
result["SHA1"] = p.HashSHA1
|
result["SHA1"] = p.Files[0].Checksums.SHA1
|
||||||
}
|
}
|
||||||
if p.HashSHA256 != "" {
|
if p.Files[0].Checksums.SHA256 != "" {
|
||||||
result["SHA256"] = p.HashSHA256
|
result["SHA256"] = p.Files[0].Checksums.SHA256
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Depends != nil {
|
if p.Depends != nil {
|
||||||
@@ -137,29 +195,123 @@ func (p *Package) Stanza() (result Stanza) {
|
|||||||
if p.Recommends != nil {
|
if p.Recommends != nil {
|
||||||
result["Recommends"] = strings.Join(p.Recommends, ", ")
|
result["Recommends"] = strings.Join(p.Recommends, ", ")
|
||||||
}
|
}
|
||||||
|
if p.Provides != nil {
|
||||||
|
result["Provides"] = strings.Join(p.Provides, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
result["Size"] = fmt.Sprintf("%d", p.Filesize)
|
result["Size"] = fmt.Sprintf("%d", p.Files[0].Checksums.Size)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equals compares two packages to be identical
|
// Equals compares two packages to be identical
|
||||||
func (p *Package) Equals(p2 *Package) bool {
|
func (p *Package) Equals(p2 *Package) bool {
|
||||||
return p.Name == p2.Name && p.Version == p2.Version && p.Filename == p2.Filename &&
|
if len(p.Files) != len(p2.Files) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, f := range p.Files {
|
||||||
|
if p2.Files[i] != f {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Name == p2.Name && p.Version == p2.Version &&
|
||||||
p.Architecture == p2.Architecture && utils.StrSlicesEqual(p.Depends, p2.Depends) &&
|
p.Architecture == p2.Architecture && utils.StrSlicesEqual(p.Depends, p2.Depends) &&
|
||||||
utils.StrSlicesEqual(p.PreDepends, p2.PreDepends) && utils.StrSlicesEqual(p.Suggests, p2.Suggests) &&
|
utils.StrSlicesEqual(p.PreDepends, p2.PreDepends) && utils.StrSlicesEqual(p.Suggests, p2.Suggests) &&
|
||||||
utils.StrSlicesEqual(p.Recommends, p2.Recommends) && utils.StrMapsEqual(p.Extra, p2.Extra) &&
|
utils.StrSlicesEqual(p.Recommends, p2.Recommends) && utils.StrMapsEqual(p.Extra, p2.Extra) &&
|
||||||
p.Filesize == p2.Filesize && p.HashMD5 == p2.HashMD5 && p.HashSHA1 == p2.HashSHA1 &&
|
p.Source == p2.Source && utils.StrSlicesEqual(p.Provides, p2.Provides)
|
||||||
p.HashSHA256 == p2.HashSHA256 && p.Source == p2.Source
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyFile verifies integrity and existence of local files for the package
|
// LinkFromPool links package file from pool to dist's pool location
|
||||||
func (p *Package) VerifyFile(filepath string) bool {
|
func (p *Package) LinkFromPool(packageRepo *Repository, prefix string, component string) error {
|
||||||
st, err := os.Stat(filepath)
|
poolDir, err := p.PoolDirectory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return err
|
||||||
}
|
}
|
||||||
return st.Size() == p.Filesize
|
|
||||||
|
for i, f := range p.Files {
|
||||||
|
sourcePath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
relPath, err := packageRepo.LinkFromPool(prefix, component, sourcePath, poolDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Files[i].Filename = relPath
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PoolDirectory returns directory in package pool for this package files
|
||||||
|
func (p *Package) PoolDirectory() (string, error) {
|
||||||
|
source := p.Source
|
||||||
|
if source == "" {
|
||||||
|
source = p.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(source) < 2 {
|
||||||
|
return "", fmt.Errorf("package source %s too short", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
var subdir string
|
||||||
|
if strings.HasPrefix(source, "lib") {
|
||||||
|
subdir = source[:4]
|
||||||
|
} else {
|
||||||
|
subdir = source[:1]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(subdir, source), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageDownloadTask is a element of download queue for the package
|
||||||
|
type PackageDownloadTask struct {
|
||||||
|
RepoURI string
|
||||||
|
DestinationPath string
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadList returns list of missing package files for download in format
|
||||||
|
// [[srcpath, dstpath]]
|
||||||
|
func (p *Package) DownloadList(packageRepo *Repository) (result []PackageDownloadTask, err error) {
|
||||||
|
result = make([]PackageDownloadTask, 0, 1)
|
||||||
|
|
||||||
|
for _, f := range p.Files {
|
||||||
|
poolPath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
verified, err := f.Verify(packageRepo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !verified {
|
||||||
|
result = append(result, PackageDownloadTask{RepoURI: f.Filename, DestinationPath: poolPath, Size: f.Checksums.Size})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyFiles verifies that all package files have neen correctly downloaded
|
||||||
|
func (p *Package) VerifyFiles(packageRepo *Repository) (result bool, err error) {
|
||||||
|
result = true
|
||||||
|
|
||||||
|
for _, f := range p.Files {
|
||||||
|
result, err = f.Verify(packageRepo)
|
||||||
|
if err != nil || !result {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageCollection does management of packages in DB
|
// PackageCollection does management of packages in DB
|
||||||
|
|||||||
Vendored
+147
-7
@@ -3,9 +3,11 @@ package debian
|
|||||||
import (
|
import (
|
||||||
"github.com/smira/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
. "launchpad.net/gocheck"
|
. "launchpad.net/gocheck"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var packageStanza = Stanza{"Source": "alien-arena", "Depends": "libc6 (>= 2.7), alien-arena-data (>= 7.40)", "Filename": "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb", "SHA1": "46955e48cad27410a83740a21d766ce362364024", "SHA256": "eb4afb9885cba6dc70cccd05b910b2dbccc02c5900578be5e99f0d3dbf9d76a5", "Priority": "extra", "Maintainer": "Debian Games Team <pkg-games-devel@lists.alioth.debian.org>", "Description": "Common files for Alien Arena client and server ALIEN ARENA is a standalone 3D first person online deathmatch shooter\n crafted from the original source code of Quake II and Quake III, released\n by id Software under the GPL license. With features including 32 bit\n graphics, new particle engine and effects, light blooms, reflective water,\n hi resolution textures and skins, hi poly models, stain maps, ALIEN ARENA\n pushes the envelope of graphical beauty rivaling today's top games.\n .\n This package installs the common files for Alien Arena.\n", "Homepage": "http://red.planetarena.org", "Tag": "role::app-data, role::shared-lib, special::auto-inst-parts", "Installed-Size": "456", "Version": "7.40-2", "Replaces": "alien-arena (<< 7.33-1)", "Size": "187518", "MD5sum": "1e8cba92c41420aa7baa8a5718d67122", "Package": "alien-arena-common", "Section": "contrib/games", "Architecture": "i386"}
|
var packageStanza = Stanza{"Source": "alien-arena", "Pre-Depends": "dpkg (>= 1.6)", "Suggests": "alien-arena-mars", "Recommends": "aliean-arena-luna", "Depends": "libc6 (>= 2.7), alien-arena-data (>= 7.40)", "Filename": "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb", "SHA1": "46955e48cad27410a83740a21d766ce362364024", "SHA256": "eb4afb9885cba6dc70cccd05b910b2dbccc02c5900578be5e99f0d3dbf9d76a5", "Priority": "extra", "Maintainer": "Debian Games Team <pkg-games-devel@lists.alioth.debian.org>", "Description": "Common files for Alien Arena client and server ALIEN ARENA is a standalone 3D first person online deathmatch shooter\n crafted from the original source code of Quake II and Quake III, released\n by id Software under the GPL license. With features including 32 bit\n graphics, new particle engine and effects, light blooms, reflective water,\n hi resolution textures and skins, hi poly models, stain maps, ALIEN ARENA\n pushes the envelope of graphical beauty rivaling today's top games.\n .\n This package installs the common files for Alien Arena.\n", "Homepage": "http://red.planetarena.org", "Tag": "role::app-data, role::shared-lib, special::auto-inst-parts", "Installed-Size": "456", "Version": "7.40-2", "Replaces": "alien-arena (<< 7.33-1)", "Size": "187518", "MD5sum": "1e8cba92c41420aa7baa8a5718d67122", "Package": "alien-arena-common", "Section": "contrib/games", "Architecture": "i386"}
|
||||||
|
|
||||||
type PackageSuite struct {
|
type PackageSuite struct {
|
||||||
stanza Stanza
|
stanza Stanza
|
||||||
@@ -17,22 +19,70 @@ func (s *PackageSuite) SetUpTest(c *C) {
|
|||||||
s.stanza = packageStanza.Copy()
|
s.stanza = packageStanza.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestPackageFileVerify(c *C) {
|
||||||
|
packageRepo := NewRepository(c.MkDir())
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
poolPath, _ := packageRepo.PoolPath(p.Files[0].Filename, p.Files[0].Checksums.MD5)
|
||||||
|
|
||||||
|
result, err := p.Files[0].Verify(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
|
err = os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.WriteString("abcde")
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
result, err = p.Files[0].Verify(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
|
result, err = p.VerifyFiles(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
|
p.Files[0].Checksums.Size = 5
|
||||||
|
result, err = p.Files[0].Verify(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(result, Equals, true)
|
||||||
|
|
||||||
|
result, err = p.VerifyFiles(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(result, Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestNewFromPara(c *C) {
|
func (s *PackageSuite) TestNewFromPara(c *C) {
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
c.Check(p.Name, Equals, "alien-arena-common")
|
c.Check(p.Name, Equals, "alien-arena-common")
|
||||||
c.Check(p.Version, Equals, "7.40-2")
|
c.Check(p.Version, Equals, "7.40-2")
|
||||||
c.Check(p.Architecture, Equals, "i386")
|
c.Check(p.Architecture, Equals, "i386")
|
||||||
c.Check(p.Filename, Equals, "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb")
|
c.Check(p.Provides, DeepEquals, []string(nil))
|
||||||
|
c.Check(p.Files, HasLen, 1)
|
||||||
|
c.Check(p.Files[0].Filename, Equals, "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb")
|
||||||
|
c.Check(p.Files[0].Checksums.Size, Equals, int64(187518))
|
||||||
|
c.Check(p.Files[0].Checksums.MD5, Equals, "1e8cba92c41420aa7baa8a5718d67122")
|
||||||
c.Check(p.Depends, DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)"})
|
c.Check(p.Depends, DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)"})
|
||||||
c.Check(p.Suggests, IsNil)
|
}
|
||||||
c.Check(p.Filesize, Equals, int64(187518))
|
|
||||||
|
func (s *PackageSuite) TestWithProvides(c *C) {
|
||||||
|
s.stanza["Provides"] = "arena"
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
|
c.Check(p.Name, Equals, "alien-arena-common")
|
||||||
|
c.Check(p.Provides, DeepEquals, []string{"arena"})
|
||||||
|
|
||||||
|
st := p.Stanza()
|
||||||
|
c.Check(st["Provides"], Equals, "arena")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestKey(c *C) {
|
func (s *PackageSuite) TestKey(c *C) {
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
c.Check(p.Key(), DeepEquals, []byte("Palien-arena-common 7.40-2 i386"))
|
c.Check(p.Key(), DeepEquals, []byte("Pi386 alien-arena-common 7.40-2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestEncodeDecode(c *C) {
|
func (s *PackageSuite) TestEncodeDecode(c *C) {
|
||||||
@@ -60,12 +110,102 @@ func (s *PackageSuite) TestString(c *C) {
|
|||||||
func (s *PackageSuite) TestEquals(c *C) {
|
func (s *PackageSuite) TestEquals(c *C) {
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
stanza2 := packageStanza.Copy()
|
p2 := NewPackageFromControlFile(packageStanza.Copy())
|
||||||
p2 := NewPackageFromControlFile(stanza2)
|
|
||||||
c.Check(p.Equals(p2), Equals, true)
|
c.Check(p.Equals(p2), Equals, true)
|
||||||
|
|
||||||
p2.Depends = []string{"package1"}
|
p2.Depends = []string{"package1"}
|
||||||
c.Check(p.Equals(p2), Equals, false)
|
c.Check(p.Equals(p2), Equals, false)
|
||||||
|
|
||||||
|
p2 = NewPackageFromControlFile(packageStanza.Copy())
|
||||||
|
p2.Files[0].Checksums.MD5 = "abcdefabcdef"
|
||||||
|
c.Check(p.Equals(p2), Equals, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestMatchesArchitecture(c *C) {
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
c.Check(p.MatchesArchitecture("i386"), Equals, true)
|
||||||
|
c.Check(p.MatchesArchitecture("amd64"), Equals, false)
|
||||||
|
|
||||||
|
s.stanza = packageStanza.Copy()
|
||||||
|
s.stanza["Architecture"] = "all"
|
||||||
|
p = NewPackageFromControlFile(s.stanza)
|
||||||
|
c.Check(p.MatchesArchitecture("i386"), Equals, true)
|
||||||
|
c.Check(p.MatchesArchitecture("amd64"), Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestGetDependencies(c *C) {
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
c.Check(p.GetDependencies(0), DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)", "dpkg (>= 1.6)"})
|
||||||
|
c.Check(p.GetDependencies(DepFollowSuggests), DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)", "dpkg (>= 1.6)", "alien-arena-mars"})
|
||||||
|
c.Check(p.GetDependencies(DepFollowSuggests|DepFollowRecommends), DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)", "dpkg (>= 1.6)", "aliean-arena-luna", "alien-arena-mars"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestPoolDirectory(c *C) {
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
dir, err := p.PoolDirectory()
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(dir, Equals, "a/alien-arena")
|
||||||
|
|
||||||
|
p = NewPackageFromControlFile(packageStanza.Copy())
|
||||||
|
p.Source = ""
|
||||||
|
dir, err = p.PoolDirectory()
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(dir, Equals, "a/alien-arena-common")
|
||||||
|
|
||||||
|
p = NewPackageFromControlFile(packageStanza.Copy())
|
||||||
|
p.Source = "libarena"
|
||||||
|
dir, err = p.PoolDirectory()
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(dir, Equals, "liba/libarena")
|
||||||
|
|
||||||
|
p = NewPackageFromControlFile(packageStanza.Copy())
|
||||||
|
p.Source = "l"
|
||||||
|
_, err = p.PoolDirectory()
|
||||||
|
c.Check(err, ErrorMatches, ".* too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestLinkFromPool(c *C) {
|
||||||
|
packageRepo := NewRepository(c.MkDir())
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
|
poolPath, _ := packageRepo.PoolPath(p.Files[0].Filename, p.Files[0].Checksums.MD5)
|
||||||
|
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
err = p.LinkFromPool(packageRepo, "", "non-free")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(p.Files[0].Filename, Equals, "pool/non-free/a/alien-arena/alien-arena-common_7.40-2_i386.deb")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PackageSuite) TestDownloadList(c *C) {
|
||||||
|
packageRepo := NewRepository(c.MkDir())
|
||||||
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
p.Files[0].Checksums.Size = 5
|
||||||
|
poolPath, _ := packageRepo.PoolPath(p.Files[0].Filename, p.Files[0].Checksums.MD5)
|
||||||
|
|
||||||
|
list, err := p.DownloadList(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(list, DeepEquals, []PackageDownloadTask{
|
||||||
|
PackageDownloadTask{
|
||||||
|
RepoURI: "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb",
|
||||||
|
DestinationPath: poolPath,
|
||||||
|
Size: 5}})
|
||||||
|
|
||||||
|
err = os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.WriteString("abcde")
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
list, err = p.DownloadList(packageRepo)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(list, DeepEquals, []PackageDownloadTask{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageCollectionSuite struct {
|
type PackageCollectionSuite struct {
|
||||||
|
|||||||
Vendored
+233
-27
@@ -2,8 +2,13 @@ package debian
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"code.google.com/p/go-uuid/uuid"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
"github.com/smira/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
|
"github.com/ugorji/go/codec"
|
||||||
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -11,6 +16,8 @@ import (
|
|||||||
|
|
||||||
// PublishedRepo is a published for http/ftp representation of snapshot as Debian repository
|
// PublishedRepo is a published for http/ftp representation of snapshot as Debian repository
|
||||||
type PublishedRepo struct {
|
type PublishedRepo struct {
|
||||||
|
// Internal unique ID
|
||||||
|
UUID string
|
||||||
// Prefix & distribution should be unique across all published repositories
|
// Prefix & distribution should be unique across all published repositories
|
||||||
Prefix string
|
Prefix string
|
||||||
Distribution string
|
Distribution string
|
||||||
@@ -24,15 +31,63 @@ type PublishedRepo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewPublishedRepo creates new published repository
|
// NewPublishedRepo creates new published repository
|
||||||
func NewPublishedRepo(prefix string, distribution string, component string, architectures []string, snapshot *Snapshot) *PublishedRepo {
|
func NewPublishedRepo(prefix string, distribution string, component string, architectures []string, snapshot *Snapshot) (*PublishedRepo, error) {
|
||||||
|
prefix = filepath.Clean(prefix)
|
||||||
|
if strings.HasPrefix(prefix, "/") {
|
||||||
|
prefix = prefix[1:]
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(prefix, "/") {
|
||||||
|
prefix = prefix[:len(prefix)-1]
|
||||||
|
}
|
||||||
|
prefix = filepath.Clean(prefix)
|
||||||
|
|
||||||
|
for _, component := range strings.Split(prefix, "/") {
|
||||||
|
if component == ".." || component == "dists" || component == "pool" {
|
||||||
|
return nil, fmt.Errorf("invalid prefix %s", prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &PublishedRepo{
|
return &PublishedRepo{
|
||||||
|
UUID: uuid.New(),
|
||||||
Prefix: prefix,
|
Prefix: prefix,
|
||||||
Distribution: distribution,
|
Distribution: distribution,
|
||||||
Component: component,
|
Component: component,
|
||||||
Architectures: architectures,
|
Architectures: architectures,
|
||||||
SnapshotUUID: snapshot.UUID,
|
SnapshotUUID: snapshot.UUID,
|
||||||
snapshot: snapshot,
|
snapshot: snapshot,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns human-readable represenation of PublishedRepo
|
||||||
|
func (p *PublishedRepo) String() string {
|
||||||
|
var archs string
|
||||||
|
|
||||||
|
if len(p.Architectures) > 0 {
|
||||||
|
archs = fmt.Sprintf(" [%s]", strings.Join(p.Architectures, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s/%s (%s)%s publishes %s", p.Prefix, p.Distribution, p.Component, archs, p.snapshot.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns unique key identifying PublishedRepo
|
||||||
|
func (p *PublishedRepo) Key() []byte {
|
||||||
|
return []byte("U" + p.Prefix + ">>" + p.Distribution)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode does msgpack encoding of PublishedRepo
|
||||||
|
func (p *PublishedRepo) Encode() []byte {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
encoder := codec.NewEncoder(&buf, &codec.MsgpackHandle{})
|
||||||
|
encoder.Encode(p)
|
||||||
|
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes msgpack representation into PublishedRepo
|
||||||
|
func (p *PublishedRepo) Decode(input []byte) error {
|
||||||
|
decoder := codec.NewDecoderBytes(input, &codec.MsgpackHandle{})
|
||||||
|
return decoder.Decode(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
||||||
@@ -48,15 +103,7 @@ func (p *PublishedRepo) Publish(repo *Repository, packageCollection *PackageColl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load all packages
|
// Load all packages
|
||||||
list := NewPackageList()
|
list, err := NewPackageListFromRefList(p.snapshot.RefList(), packageCollection)
|
||||||
|
|
||||||
err = p.snapshot.RefList().ForEach(func(key []byte) error {
|
|
||||||
pkg, err := packageCollection.ByKey(key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return list.Add(pkg)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load packages: %s", err)
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
}
|
}
|
||||||
@@ -65,14 +112,8 @@ func (p *PublishedRepo) Publish(repo *Repository, packageCollection *PackageColl
|
|||||||
return fmt.Errorf("repository is empty, can't publish")
|
return fmt.Errorf("repository is empty, can't publish")
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Architectures == nil {
|
if len(p.Architectures) == 0 {
|
||||||
p.Architectures = make([]string, 0, 10)
|
p.Architectures = list.Architectures()
|
||||||
list.ForEach(func(pkg *Package) error {
|
|
||||||
if pkg.Architecture != "all" && !utils.StrSliceHasItem(p.Architectures, pkg.Architecture) {
|
|
||||||
p.Architectures = append(p.Architectures, pkg.Architecture)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.Architectures) == 0 {
|
if len(p.Architectures) == 0 {
|
||||||
@@ -97,19 +138,12 @@ func (p *PublishedRepo) Publish(repo *Repository, packageCollection *PackageColl
|
|||||||
bufWriter := bufio.NewWriter(packagesFile)
|
bufWriter := bufio.NewWriter(packagesFile)
|
||||||
|
|
||||||
err = list.ForEach(func(pkg *Package) error {
|
err = list.ForEach(func(pkg *Package) error {
|
||||||
if pkg.Architecture == arch || pkg.Architecture == "all" {
|
if pkg.MatchesArchitecture(arch) {
|
||||||
source := pkg.Source
|
err = pkg.LinkFromPool(repo, p.Prefix, p.Component)
|
||||||
if source == "" {
|
|
||||||
source = pkg.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := repo.LinkFromPool(p.Prefix, p.Component, pkg.Filename, pkg.HashMD5, source)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg.Filename = path
|
|
||||||
|
|
||||||
err = pkg.Stanza().WriteTo(bufWriter)
|
err = pkg.Stanza().WriteTo(bufWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -210,3 +244,175 @@ func (p *PublishedRepo) Publish(repo *Repository, packageCollection *PackageColl
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveFiles removes files that were created by Publish
|
||||||
|
//
|
||||||
|
// It can remove prefix fully, and part of pool (for specific component)
|
||||||
|
func (p *PublishedRepo) RemoveFiles(repo *Repository, removePrefix, removePoolComponent bool) error {
|
||||||
|
if removePrefix {
|
||||||
|
err := repo.RemoveDirs(filepath.Join(p.Prefix, "dists"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.RemoveDirs(filepath.Join(p.Prefix, "pool"))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := repo.RemoveDirs(filepath.Join(p.Prefix, "dists", p.Distribution))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if removePoolComponent {
|
||||||
|
err = repo.RemoveDirs(filepath.Join(p.Prefix, "pool", p.Component))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishedRepoCollection does listing, updating/adding/deleting of PublishedRepos
|
||||||
|
type PublishedRepoCollection struct {
|
||||||
|
db database.Storage
|
||||||
|
list []*PublishedRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPublishedRepoCollection loads PublishedRepos from DB and makes up collection
|
||||||
|
func NewPublishedRepoCollection(db database.Storage) *PublishedRepoCollection {
|
||||||
|
result := &PublishedRepoCollection{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
|
||||||
|
blobs := db.FetchByPrefix([]byte("U"))
|
||||||
|
result.list = make([]*PublishedRepo, 0, len(blobs))
|
||||||
|
|
||||||
|
for _, blob := range blobs {
|
||||||
|
r := &PublishedRepo{}
|
||||||
|
if err := r.Decode(blob); err != nil {
|
||||||
|
log.Printf("Error decoding published repo: %s\n", err)
|
||||||
|
} else {
|
||||||
|
result.list = append(result.list, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends new repo to collection and saves it
|
||||||
|
func (collection *PublishedRepoCollection) Add(repo *PublishedRepo) error {
|
||||||
|
if collection.CheckDuplicate(repo) != nil {
|
||||||
|
return fmt.Errorf("published repo with prefix/distribution %s/%s already exists", repo.Prefix, repo.Distribution)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := collection.Update(repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.list = append(collection.list, repo)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckDuplicate verifies that there's no published repo with the same name
|
||||||
|
func (collection *PublishedRepoCollection) CheckDuplicate(repo *PublishedRepo) *PublishedRepo {
|
||||||
|
for _, r := range collection.list {
|
||||||
|
if r.Prefix == repo.Prefix && r.Distribution == repo.Distribution {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update stores updated information about repo in DB
|
||||||
|
func (collection *PublishedRepoCollection) Update(repo *PublishedRepo) error {
|
||||||
|
err := collection.db.Put(repo.Key(), repo.Encode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadComplete loads additional information for remote repo
|
||||||
|
func (collection *PublishedRepoCollection) LoadComplete(repo *PublishedRepo, snapshotCollection *SnapshotCollection) error {
|
||||||
|
snapshot, err := snapshotCollection.ByUUID(repo.SnapshotUUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.snapshot = snapshot
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByPrefixDistribution looks up repository by prefix & distribution
|
||||||
|
func (collection *PublishedRepoCollection) ByPrefixDistribution(prefix, distribution string) (*PublishedRepo, error) {
|
||||||
|
for _, r := range collection.list {
|
||||||
|
if r.Prefix == prefix && r.Distribution == distribution {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("published repo with prefix/distribution %s/%s not found", prefix, distribution)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByUUID looks up repository by uuid
|
||||||
|
func (collection *PublishedRepoCollection) ByUUID(uuid string) (*PublishedRepo, error) {
|
||||||
|
for _, r := range collection.list {
|
||||||
|
if r.UUID == uuid {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("published repo with uuid %s not found", uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForEach runs method for each repository
|
||||||
|
func (collection *PublishedRepoCollection) ForEach(handler func(*PublishedRepo) error) error {
|
||||||
|
var err error
|
||||||
|
for _, r := range collection.list {
|
||||||
|
err = handler(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns number of remote repos
|
||||||
|
func (collection *PublishedRepoCollection) Len() int {
|
||||||
|
return len(collection.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes published repository, cleaning up directories, files
|
||||||
|
func (collection *PublishedRepoCollection) Remove(packageRepo *Repository, prefix, distribution string) error {
|
||||||
|
repo, err := collection.ByPrefixDistribution(prefix, distribution)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
removePrefix := true
|
||||||
|
removePoolComponent := true
|
||||||
|
repoPosition := -1
|
||||||
|
|
||||||
|
for i, r := range collection.list {
|
||||||
|
if r == repo {
|
||||||
|
repoPosition = i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r.Prefix == repo.Prefix {
|
||||||
|
removePrefix = false
|
||||||
|
if r.Component == repo.Component {
|
||||||
|
removePoolComponent = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = repo.RemoveFiles(packageRepo, removePrefix, removePoolComponent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.list[len(collection.list)-1], collection.list[repoPosition], collection.list =
|
||||||
|
nil, collection.list[len(collection.list)-1], collection.list[:len(collection.list)-1]
|
||||||
|
|
||||||
|
return collection.db.Delete(repo.Key())
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+365
-3
@@ -1,6 +1,7 @@
|
|||||||
package debian
|
package debian
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/smira/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
. "launchpad.net/gocheck"
|
. "launchpad.net/gocheck"
|
||||||
"os"
|
"os"
|
||||||
@@ -25,6 +26,7 @@ type PublishedRepoSuite struct {
|
|||||||
PackageListMixinSuite
|
PackageListMixinSuite
|
||||||
repo *PublishedRepo
|
repo *PublishedRepo
|
||||||
packageRepo *Repository
|
packageRepo *Repository
|
||||||
|
snapshot *Snapshot
|
||||||
db database.Storage
|
db database.Storage
|
||||||
packageCollection *PackageCollection
|
packageCollection *PackageCollection
|
||||||
}
|
}
|
||||||
@@ -41,22 +43,91 @@ func (s *PublishedRepoSuite) SetUpTest(c *C) {
|
|||||||
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
||||||
repo.packageRefs = s.reflist
|
repo.packageRefs = s.reflist
|
||||||
|
|
||||||
snapshot, _ := NewSnapshotFromRepository("snap", repo)
|
s.snapshot, _ = NewSnapshotFromRepository("snap", repo)
|
||||||
|
|
||||||
s.repo = NewPublishedRepo("ppa", "squeeze", "main", nil, snapshot)
|
s.repo, _ = NewPublishedRepo("ppa", "squeeze", "main", nil, s.snapshot)
|
||||||
|
|
||||||
s.packageCollection = NewPackageCollection(s.db)
|
s.packageCollection = NewPackageCollection(s.db)
|
||||||
s.packageCollection.Update(s.p1)
|
s.packageCollection.Update(s.p1)
|
||||||
s.packageCollection.Update(s.p2)
|
s.packageCollection.Update(s.p2)
|
||||||
s.packageCollection.Update(s.p3)
|
s.packageCollection.Update(s.p3)
|
||||||
|
|
||||||
poolPath, _ := s.packageRepo.PoolPath(s.p1.Filename, s.p1.HashMD5)
|
poolPath, _ := s.packageRepo.PoolPath(s.p1.Files[0].Filename, s.p1.Files[0].Checksums.MD5)
|
||||||
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
f, err := os.Create(poolPath)
|
f, err := os.Create(poolPath)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoSuite) TearDownTest(c *C) {
|
||||||
|
s.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoSuite) TestPrefixNormalization(c *C) {
|
||||||
|
|
||||||
|
for _, t := range []struct {
|
||||||
|
prefix string
|
||||||
|
expected string
|
||||||
|
errorExpected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
prefix: "ppa",
|
||||||
|
expected: "ppa",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "",
|
||||||
|
expected: ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "/",
|
||||||
|
expected: ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "//",
|
||||||
|
expected: ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "//ppa/",
|
||||||
|
expected: "ppa",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "ppa/..",
|
||||||
|
expected: ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "ppa/ubuntu/",
|
||||||
|
expected: "ppa/ubuntu",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "ppa/../ubuntu/",
|
||||||
|
expected: "ubuntu",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "../ppa/",
|
||||||
|
errorExpected: "invalid prefix .*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "../ppa/../ppa/",
|
||||||
|
errorExpected: "invalid prefix .*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "ppa/dists",
|
||||||
|
errorExpected: "invalid prefix .*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: "ppa/pool",
|
||||||
|
errorExpected: "invalid prefix .*",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
repo, err := NewPublishedRepo(t.prefix, "squeeze", "main", nil, s.snapshot)
|
||||||
|
if t.errorExpected != "" {
|
||||||
|
c.Check(err, ErrorMatches, t.errorExpected)
|
||||||
|
} else {
|
||||||
|
c.Check(repo.Prefix, Equals, t.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoSuite) TestPublish(c *C) {
|
func (s *PublishedRepoSuite) TestPublish(c *C) {
|
||||||
err := s.repo.Publish(s.packageRepo, s.packageCollection, &NullSigner{})
|
err := s.repo.Publish(s.packageRepo, s.packageCollection, &NullSigner{})
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
@@ -93,3 +164,294 @@ func (s *PublishedRepoSuite) TestPublish(c *C) {
|
|||||||
_, err = os.Stat(filepath.Join(s.packageRepo.RootPath, "public/ppa/pool/main/a/alien-arena/alien-arena-common_7.40-2_i386.deb"))
|
_, err = os.Stat(filepath.Join(s.packageRepo.RootPath, "public/ppa/pool/main/a/alien-arena/alien-arena-common_7.40-2_i386.deb"))
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoSuite) TestString(c *C) {
|
||||||
|
c.Check(s.repo.String(), Equals,
|
||||||
|
"ppa/squeeze (main) publishes [snap]: Snapshot from mirror [yandex]: http://mirror.yandex.ru/debian/ squeeze")
|
||||||
|
repo, _ := NewPublishedRepo("", "squeeze", "main", nil, s.snapshot)
|
||||||
|
c.Check(repo.String(), Equals,
|
||||||
|
"./squeeze (main) publishes [snap]: Snapshot from mirror [yandex]: http://mirror.yandex.ru/debian/ squeeze")
|
||||||
|
repo, _ = NewPublishedRepo("", "squeeze", "main", []string{"i386", "amd64"}, s.snapshot)
|
||||||
|
c.Check(repo.String(), Equals,
|
||||||
|
"./squeeze (main) [i386, amd64] publishes [snap]: Snapshot from mirror [yandex]: http://mirror.yandex.ru/debian/ squeeze")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoSuite) TestKey(c *C) {
|
||||||
|
c.Check(s.repo.Key(), DeepEquals, []byte("Uppa>>squeeze"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoSuite) TestEncodeDecode(c *C) {
|
||||||
|
encoded := s.repo.Encode()
|
||||||
|
repo := &PublishedRepo{}
|
||||||
|
err := repo.Decode(encoded)
|
||||||
|
|
||||||
|
s.repo.snapshot = nil
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(repo, DeepEquals, s.repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublishedRepoCollectionSuite struct {
|
||||||
|
PackageListMixinSuite
|
||||||
|
db database.Storage
|
||||||
|
snapshotCollection *SnapshotCollection
|
||||||
|
collection *PublishedRepoCollection
|
||||||
|
snap1, snap2 *Snapshot
|
||||||
|
repo1, repo2, repo3 *PublishedRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Suite(&PublishedRepoCollectionSuite{})
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) SetUpTest(c *C) {
|
||||||
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
|
|
||||||
|
s.snapshotCollection = NewSnapshotCollection(s.db)
|
||||||
|
|
||||||
|
s.snap1 = NewSnapshotFromPackageList("snap1", []*Snapshot{}, NewPackageList(), "desc1")
|
||||||
|
s.snap2 = NewSnapshotFromPackageList("snap2", []*Snapshot{}, NewPackageList(), "desc2")
|
||||||
|
|
||||||
|
s.snapshotCollection.Add(s.snap1)
|
||||||
|
s.snapshotCollection.Add(s.snap2)
|
||||||
|
|
||||||
|
s.repo1, _ = NewPublishedRepo("ppa", "anaconda", "main", []string{}, s.snap1)
|
||||||
|
s.repo2, _ = NewPublishedRepo("", "anaconda", "main", []string{}, s.snap2)
|
||||||
|
s.repo3, _ = NewPublishedRepo("ppa", "anaconda", "main", []string{}, s.snap2)
|
||||||
|
|
||||||
|
s.collection = NewPublishedRepoCollection(s.db)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) TearDownTest(c *C) {
|
||||||
|
s.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) TestAddByName(c *C) {
|
||||||
|
r, err := s.collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
|
c.Assert(s.collection.Add(s.repo1), IsNil)
|
||||||
|
c.Assert(s.collection.Add(s.repo1), ErrorMatches, ".*already exists")
|
||||||
|
c.Assert(s.collection.CheckDuplicate(s.repo2), IsNil)
|
||||||
|
c.Assert(s.collection.Add(s.repo2), IsNil)
|
||||||
|
c.Assert(s.collection.Add(s.repo3), ErrorMatches, ".*already exists")
|
||||||
|
c.Assert(s.collection.CheckDuplicate(s.repo3), Equals, s.repo1)
|
||||||
|
|
||||||
|
r, err = s.collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.collection.LoadComplete(r, s.snapshotCollection)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(r.String(), Equals, s.repo1.String())
|
||||||
|
|
||||||
|
collection := NewPublishedRepoCollection(s.db)
|
||||||
|
r, err = collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.collection.LoadComplete(r, s.snapshotCollection)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(r.String(), Equals, s.repo1.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) TestByUUID(c *C) {
|
||||||
|
r, err := s.collection.ByUUID(s.repo1.UUID)
|
||||||
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
|
c.Assert(s.collection.Add(s.repo1), IsNil)
|
||||||
|
|
||||||
|
r, err = s.collection.ByUUID(s.repo1.UUID)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.collection.LoadComplete(r, s.snapshotCollection)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(r.String(), Equals, s.repo1.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) TestUpdateLoadComplete(c *C) {
|
||||||
|
c.Assert(s.collection.Update(s.repo1), IsNil)
|
||||||
|
|
||||||
|
collection := NewPublishedRepoCollection(s.db)
|
||||||
|
r, err := collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(r.snapshot, IsNil)
|
||||||
|
c.Assert(s.collection.LoadComplete(r, s.snapshotCollection), IsNil)
|
||||||
|
c.Assert(r.snapshot.UUID, Equals, s.repo1.snapshot.UUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoCollectionSuite) TestForEachAndLen(c *C) {
|
||||||
|
s.collection.Add(s.repo1)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
err := s.collection.ForEach(func(*PublishedRepo) error {
|
||||||
|
count++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
c.Assert(count, Equals, 1)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
c.Check(s.collection.Len(), Equals, 1)
|
||||||
|
|
||||||
|
e := errors.New("c")
|
||||||
|
|
||||||
|
err = s.collection.ForEach(func(*PublishedRepo) error {
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
c.Assert(err, Equals, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathExistsChecker struct {
|
||||||
|
*CheckerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
var PathExists = &pathExistsChecker{
|
||||||
|
&CheckerInfo{Name: "PathExists", Params: []string{"path"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (checker *pathExistsChecker) Check(params []interface{}, names []string) (result bool, error string) {
|
||||||
|
_, err := os.Stat(params[0].(string))
|
||||||
|
return err == nil, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublishedRepoRemoveSuite struct {
|
||||||
|
PackageListMixinSuite
|
||||||
|
db database.Storage
|
||||||
|
snapshotCollection *SnapshotCollection
|
||||||
|
collection *PublishedRepoCollection
|
||||||
|
packageRepo *Repository
|
||||||
|
snap1 *Snapshot
|
||||||
|
repo1, repo2, repo3, repo4 *PublishedRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Suite(&PublishedRepoRemoveSuite{})
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
|
||||||
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
|
|
||||||
|
s.snapshotCollection = NewSnapshotCollection(s.db)
|
||||||
|
|
||||||
|
s.snap1 = NewSnapshotFromPackageList("snap1", []*Snapshot{}, NewPackageList(), "desc1")
|
||||||
|
|
||||||
|
s.snapshotCollection.Add(s.snap1)
|
||||||
|
|
||||||
|
s.repo1, _ = NewPublishedRepo("ppa", "anaconda", "main", []string{}, s.snap1)
|
||||||
|
s.repo2, _ = NewPublishedRepo("", "anaconda", "main", []string{}, s.snap1)
|
||||||
|
s.repo3, _ = NewPublishedRepo("ppa", "meduza", "main", []string{}, s.snap1)
|
||||||
|
s.repo4, _ = NewPublishedRepo("ppa", "osminog", "contrib", []string{}, s.snap1)
|
||||||
|
|
||||||
|
s.collection = NewPublishedRepoCollection(s.db)
|
||||||
|
s.collection.Add(s.repo1)
|
||||||
|
s.collection.Add(s.repo2)
|
||||||
|
s.collection.Add(s.repo3)
|
||||||
|
s.collection.Add(s.repo4)
|
||||||
|
|
||||||
|
s.packageRepo = NewRepository(c.MkDir())
|
||||||
|
s.packageRepo.MkDir("ppa/dists/anaconda")
|
||||||
|
s.packageRepo.MkDir("ppa/dists/meduza")
|
||||||
|
s.packageRepo.MkDir("ppa/dists/osminog")
|
||||||
|
s.packageRepo.MkDir("ppa/pool/main")
|
||||||
|
s.packageRepo.MkDir("ppa/pool/contrib")
|
||||||
|
s.packageRepo.MkDir("dists/anaconda")
|
||||||
|
s.packageRepo.MkDir("pool/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TearDownTest(c *C) {
|
||||||
|
s.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveFilesOnlyDist(c *C) {
|
||||||
|
s.repo1.RemoveFiles(s.packageRepo, false, false)
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), PathExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveFilesWithPool(c *C) {
|
||||||
|
s.repo1.RemoveFiles(s.packageRepo, false, true)
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), PathExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveFilesWithPrefix(c *C) {
|
||||||
|
s.repo1.RemoveFiles(s.packageRepo, true, true)
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), PathExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveFilesWithPrefixRoot(c *C) {
|
||||||
|
s.repo2.RemoveFiles(s.packageRepo, true, true)
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), Not(PathExists))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2(c *C) {
|
||||||
|
err := s.collection.Remove(s.packageRepo, "ppa", "anaconda")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
_, err = s.collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
|
collection := NewPublishedRepoCollection(s.db)
|
||||||
|
_, err = collection.ByPrefixDistribution("ppa", "anaconda")
|
||||||
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), PathExists)
|
||||||
|
|
||||||
|
err = s.collection.Remove(s.packageRepo, "ppa", "anaconda")
|
||||||
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
|
err = s.collection.Remove(s.packageRepo, "ppa", "meduza")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/main"), PathExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedRepoRemoveSuite) TestRemoveRepo3(c *C) {
|
||||||
|
err := s.collection.Remove(s.packageRepo, ".", "anaconda")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
_, err = s.collection.ByPrefixDistribution(".", "anaconda")
|
||||||
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
|
collection := NewPublishedRepoCollection(s.db)
|
||||||
|
_, err = collection.ByPrefixDistribution(".", "anaconda")
|
||||||
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/anaconda"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/meduza"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/main"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "dists/"), Not(PathExists))
|
||||||
|
c.Check(filepath.Join(s.packageRepo.PublicPath(), "pool/"), Not(PathExists))
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+36
-9
@@ -148,6 +148,8 @@ func (repo *RemoteRepo) Fetch(d utils.Downloader) error {
|
|||||||
func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageCollection, packageRepo *Repository) error {
|
func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageCollection, packageRepo *Repository) error {
|
||||||
list := NewPackageList()
|
list := NewPackageList()
|
||||||
|
|
||||||
|
fmt.Printf("Downloading & parsing package files...\n")
|
||||||
|
|
||||||
// Download and parse all Release files
|
// Download and parse all Release files
|
||||||
for _, component := range repo.Components {
|
for _, component := range repo.Components {
|
||||||
for _, architecture := range repo.Architectures {
|
for _, architecture := range repo.Architectures {
|
||||||
@@ -175,6 +177,8 @@ func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Saving packages to database...\n")
|
||||||
|
|
||||||
// Save package meta information to DB
|
// Save package meta information to DB
|
||||||
err := list.ForEach(func(p *Package) error {
|
err := list.ForEach(func(p *Package) error {
|
||||||
return packageCollection.Update(p)
|
return packageCollection.Update(p)
|
||||||
@@ -184,30 +188,48 @@ func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageC
|
|||||||
return fmt.Errorf("unable to save packages to db: %s", err)
|
return fmt.Errorf("unable to save packages to db: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download all package files
|
fmt.Printf("Building download queue...\n")
|
||||||
ch := make(chan error, list.Len())
|
|
||||||
|
// Build download queue
|
||||||
|
queued := make(map[string]PackageDownloadTask, list.Len())
|
||||||
count := 0
|
count := 0
|
||||||
|
downloadSize := int64(0)
|
||||||
|
|
||||||
err = list.ForEach(func(p *Package) error {
|
err = list.ForEach(func(p *Package) error {
|
||||||
poolPath, err := packageRepo.PoolPath(p.Filename, p.HashMD5)
|
list, err := p.DownloadList(packageRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.VerifyFile(poolPath) {
|
for _, task := range list {
|
||||||
d.Download(repo.PackageURL(p.Filename).String(), poolPath, ch)
|
key := task.RepoURI + "-" + task.DestinationPath
|
||||||
count++
|
_, found := queued[key]
|
||||||
|
if !found {
|
||||||
|
count++
|
||||||
|
downloadSize += task.Size
|
||||||
|
queued[key] = task
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to download packages: %s", err)
|
return fmt.Errorf("unable to build download queue: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := make([]string, 0)
|
fmt.Printf("Download queue: %d items, %.2f GiB size\n", count, float64(downloadSize)/(1024.0*1024.0*1024.0))
|
||||||
|
|
||||||
|
// Download all package files
|
||||||
|
ch := make(chan error, len(queued))
|
||||||
|
|
||||||
|
for _, task := range queued {
|
||||||
|
d.Download(repo.PackageURL(task.RepoURI).String(), task.DestinationPath, ch)
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for all downloads to finish
|
// Wait for all downloads to finish
|
||||||
|
errors := make([]string, 0)
|
||||||
|
|
||||||
for count > 0 {
|
for count > 0 {
|
||||||
err = <-ch
|
err = <-ch
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -217,7 +239,7 @@ func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
return fmt.Errorf("download errors: %s", strings.Join(errors, ", "))
|
return fmt.Errorf("download errors:\n %s\n", strings.Join(errors, "\n "))
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.LastDownloadDate = time.Now()
|
repo.LastDownloadDate = time.Now()
|
||||||
@@ -360,3 +382,8 @@ func (collection *RemoteRepoCollection) ForEach(handler func(*RemoteRepo) error)
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len returns number of remote repos
|
||||||
|
func (collection *RemoteRepoCollection) Len() int {
|
||||||
|
return len(collection.list)
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+6
-3
@@ -144,8 +144,9 @@ func (s *RemoteRepoSuite) TestDownload(c *C) {
|
|||||||
pkg, err := s.packageCollection.ByKey(s.repo.packageRefs.Refs[0])
|
pkg, err := s.packageCollection.ByKey(s.repo.packageRefs.Refs[0])
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
poolPath, _ := s.packageRepo.PoolPath(pkg.Filename, pkg.HashMD5)
|
result, err := pkg.VerifyFiles(s.packageRepo)
|
||||||
c.Check(pkg.VerifyFile(poolPath), Equals, true)
|
c.Check(result, Equals, true)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
c.Check(pkg.Name, Equals, "amanda-client")
|
c.Check(pkg.Name, Equals, "amanda-client")
|
||||||
}
|
}
|
||||||
@@ -219,7 +220,7 @@ func (s *RemoteRepoCollectionSuite) TestUpdateLoadComplete(c *C) {
|
|||||||
c.Assert(r.NumPackages(), Equals, 3)
|
c.Assert(r.NumPackages(), Equals, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RemoteRepoCollectionSuite) TestForEach(c *C) {
|
func (s *RemoteRepoCollectionSuite) TestForEachAndLen(c *C) {
|
||||||
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
||||||
s.collection.Add(repo)
|
s.collection.Add(repo)
|
||||||
|
|
||||||
@@ -231,6 +232,8 @@ func (s *RemoteRepoCollectionSuite) TestForEach(c *C) {
|
|||||||
c.Assert(count, Equals, 1)
|
c.Assert(count, Equals, 1)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
c.Check(s.collection.Len(), Equals, 1)
|
||||||
|
|
||||||
e := errors.New("c")
|
e := errors.New("c")
|
||||||
|
|
||||||
err = s.collection.ForEach(func(*RemoteRepo) error {
|
err = s.collection.ForEach(func(*RemoteRepo) error {
|
||||||
|
|||||||
Vendored
+12
-22
@@ -5,7 +5,6 @@ import (
|
|||||||
"github.com/smira/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Repository directory structure:
|
// Repository directory structure:
|
||||||
@@ -60,30 +59,21 @@ func (r *Repository) CreateFile(path string) (*os.File, error) {
|
|||||||
return os.Create(filepath.Join(r.RootPath, "public", path))
|
return os.Create(filepath.Join(r.RootPath, "public", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveDirs removes directory structure under public path
|
||||||
|
func (r *Repository) RemoveDirs(path string) error {
|
||||||
|
filepath := filepath.Join(r.RootPath, "public", path)
|
||||||
|
fmt.Printf("Removing %s...\n", filepath)
|
||||||
|
return os.RemoveAll(filepath)
|
||||||
|
}
|
||||||
|
|
||||||
// LinkFromPool links package file from pool to dist's pool location
|
// LinkFromPool links package file from pool to dist's pool location
|
||||||
func (r *Repository) LinkFromPool(prefix string, component string, filename string, hashMD5 string, source string) (string, error) {
|
func (r *Repository) LinkFromPool(prefix string, component string, sourcePath string, poolDirectory string) (string, error) {
|
||||||
sourcePath, err := r.PoolPath(filename, hashMD5)
|
baseName := filepath.Base(sourcePath)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(source) < 2 {
|
relPath := filepath.Join("pool", component, poolDirectory, baseName)
|
||||||
return "", fmt.Errorf("package source %s too short", source)
|
poolPath := filepath.Join(r.RootPath, "public", prefix, "pool", component, poolDirectory)
|
||||||
}
|
|
||||||
|
|
||||||
var subdir string
|
err := os.MkdirAll(poolPath, 0755)
|
||||||
if strings.HasPrefix(source, "lib") {
|
|
||||||
subdir = source[:4]
|
|
||||||
} else {
|
|
||||||
subdir = source[:1]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
baseName := filepath.Base(filename)
|
|
||||||
relPath := filepath.Join("pool", component, subdir, source, baseName)
|
|
||||||
poolPath := filepath.Join(r.RootPath, "public", prefix, "pool", component, subdir, source)
|
|
||||||
|
|
||||||
err = os.MkdirAll(poolPath, 0755)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+44
-19
@@ -52,51 +52,76 @@ func (s *RepositorySuite) TestCreateFile(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RepositorySuite) TestRemoveDirs(c *C) {
|
||||||
|
err := s.repo.MkDir("ppa/dists/squeeze/")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
file, err := s.repo.CreateFile("ppa/dists/squeeze/Release")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
err = s.repo.RemoveDirs("ppa/dists/")
|
||||||
|
|
||||||
|
_, err = os.Stat(filepath.Join(s.repo.RootPath, "public/ppa/dists/squeeze/Release"))
|
||||||
|
c.Assert(err, NotNil)
|
||||||
|
c.Assert(os.IsNotExist(err), Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *RepositorySuite) TestLinkFromPool(c *C) {
|
func (s *RepositorySuite) TestLinkFromPool(c *C) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
packageFilename string
|
prefix string
|
||||||
MD5 string
|
component string
|
||||||
source string
|
sourcePath string
|
||||||
|
poolDirectory string
|
||||||
expectedFilename string
|
expectedFilename string
|
||||||
}{
|
}{
|
||||||
{ // package name regular
|
{ // package name regular
|
||||||
packageFilename: "pool/m/mars-invaders_1.03.deb",
|
prefix: "",
|
||||||
MD5: "91b1a1480b90b9e269ca44d897b12575",
|
component: "main",
|
||||||
source: "mars-invaders",
|
sourcePath: "pool/01/ae/mars-invaders_1.03.deb",
|
||||||
|
poolDirectory: "m/mars-invaders",
|
||||||
expectedFilename: "pool/main/m/mars-invaders/mars-invaders_1.03.deb",
|
expectedFilename: "pool/main/m/mars-invaders/mars-invaders_1.03.deb",
|
||||||
},
|
},
|
||||||
{ // lib-like filename
|
{ // lib-like filename
|
||||||
packageFilename: "pool/libm/libmars-invaders_1.03.deb",
|
prefix: "",
|
||||||
MD5: "12c2a1480b90b9e269ca44d897b12575",
|
component: "main",
|
||||||
source: "libmars-invaders",
|
sourcePath: "pool/01/ae/libmars-invaders_1.03.deb",
|
||||||
|
poolDirectory: "libm/libmars-invaders",
|
||||||
expectedFilename: "pool/main/libm/libmars-invaders/libmars-invaders_1.03.deb",
|
expectedFilename: "pool/main/libm/libmars-invaders/libmars-invaders_1.03.deb",
|
||||||
},
|
},
|
||||||
{ // duplicate link, shouldn't panic
|
{ // duplicate link, shouldn't panic
|
||||||
packageFilename: "pool/m/mars-invaders_1.03.deb",
|
prefix: "",
|
||||||
MD5: "91b1a1480b90b9e269ca44d897b12575",
|
component: "main",
|
||||||
source: "mars-invaders",
|
sourcePath: "pool/01/ae/mars-invaders_1.03.deb",
|
||||||
|
poolDirectory: "m/mars-invaders",
|
||||||
expectedFilename: "pool/main/m/mars-invaders/mars-invaders_1.03.deb",
|
expectedFilename: "pool/main/m/mars-invaders/mars-invaders_1.03.deb",
|
||||||
},
|
},
|
||||||
|
{ // prefix & component
|
||||||
|
prefix: "ppa",
|
||||||
|
component: "contrib",
|
||||||
|
sourcePath: "pool/01/ae/libmars-invaders_1.04.deb",
|
||||||
|
poolDirectory: "libm/libmars-invaders",
|
||||||
|
expectedFilename: "pool/contrib/libm/libmars-invaders/libmars-invaders_1.04.deb",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range tests {
|
for _, t := range tests {
|
||||||
poolPath, err := s.repo.PoolPath(t.packageFilename, t.MD5)
|
t.sourcePath = filepath.Join(s.repo.RootPath, t.sourcePath)
|
||||||
|
|
||||||
|
err := os.MkdirAll(filepath.Dir(t.sourcePath), 0755)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = os.MkdirAll(filepath.Dir(poolPath), 0755)
|
file, err := os.Create(t.sourcePath)
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
file, err := os.Create(poolPath)
|
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
file.Write([]byte("Contents"))
|
file.Write([]byte("Contents"))
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
path, err := s.repo.LinkFromPool("", "main", t.packageFilename, t.MD5, t.source)
|
path, err := s.repo.LinkFromPool(t.prefix, t.component, t.sourcePath, t.poolDirectory)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(path, Equals, t.expectedFilename)
|
c.Assert(path, Equals, t.expectedFilename)
|
||||||
|
|
||||||
st, err := os.Stat(filepath.Join(s.repo.RootPath, "public", t.expectedFilename))
|
st, err := os.Stat(filepath.Join(s.repo.RootPath, "public", t.prefix, t.expectedFilename))
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
info := st.Sys().(*syscall.Stat_t)
|
info := st.Sys().(*syscall.Stat_t)
|
||||||
|
|||||||
Vendored
+39
@@ -46,6 +46,29 @@ func NewSnapshotFromRepository(name string, repo *RemoteRepo) (*Snapshot, error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSnapshotFromPackageList creates snapshot from PackageList
|
||||||
|
func NewSnapshotFromPackageList(name string, sources []*Snapshot, list *PackageList, description string) *Snapshot {
|
||||||
|
return NewSnapshotFromRefList(name, sources, NewPackageRefListFromPackageList(list), description)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSnapshotFromRefList creates snapshot from PackageRefList
|
||||||
|
func NewSnapshotFromRefList(name string, sources []*Snapshot, list *PackageRefList, description string) *Snapshot {
|
||||||
|
sourceUUIDs := make([]string, len(sources))
|
||||||
|
for i := range sources {
|
||||||
|
sourceUUIDs[i] = sources[i].UUID
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Snapshot{
|
||||||
|
UUID: uuid.New(),
|
||||||
|
Name: name,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
SourceKind: "snapshot",
|
||||||
|
SourceIDs: sourceUUIDs,
|
||||||
|
Description: description,
|
||||||
|
packageRefs: list,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// String returns string representation of snapshot
|
// String returns string representation of snapshot
|
||||||
func (s *Snapshot) String() string {
|
func (s *Snapshot) String() string {
|
||||||
return fmt.Sprintf("[%s]: %s", s.Name, s.Description)
|
return fmt.Sprintf("[%s]: %s", s.Name, s.Description)
|
||||||
@@ -161,6 +184,16 @@ func (collection *SnapshotCollection) ByName(name string) (*Snapshot, error) {
|
|||||||
return nil, fmt.Errorf("snapshot with name %s not found", name)
|
return nil, fmt.Errorf("snapshot with name %s not found", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByUUID looks up snapshot by UUID
|
||||||
|
func (collection *SnapshotCollection) ByUUID(uuid string) (*Snapshot, error) {
|
||||||
|
for _, s := range collection.list {
|
||||||
|
if s.UUID == uuid {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("snapshot with uuid %s not found", uuid)
|
||||||
|
}
|
||||||
|
|
||||||
// ForEach runs method for each snapshot
|
// ForEach runs method for each snapshot
|
||||||
func (collection *SnapshotCollection) ForEach(handler func(*Snapshot) error) error {
|
func (collection *SnapshotCollection) ForEach(handler func(*Snapshot) error) error {
|
||||||
var err error
|
var err error
|
||||||
@@ -172,3 +205,9 @@ func (collection *SnapshotCollection) ForEach(handler func(*Snapshot) error) err
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len returns number of snapshots in collection
|
||||||
|
// ForEach runs method for each snapshot
|
||||||
|
func (collection *SnapshotCollection) Len() int {
|
||||||
|
return len(collection.list)
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+30
-2
@@ -24,12 +24,34 @@ func (s *SnapshotSuite) TestNewSnapshotFromRepository(c *C) {
|
|||||||
c.Check(snapshot.Name, Equals, "snap1")
|
c.Check(snapshot.Name, Equals, "snap1")
|
||||||
c.Check(snapshot.NumPackages(), Equals, 3)
|
c.Check(snapshot.NumPackages(), Equals, 3)
|
||||||
c.Check(snapshot.RefList().Len(), Equals, 3)
|
c.Check(snapshot.RefList().Len(), Equals, 3)
|
||||||
|
c.Check(snapshot.SourceKind, Equals, "repo")
|
||||||
|
c.Check(snapshot.SourceIDs, DeepEquals, []string{s.repo.UUID})
|
||||||
|
|
||||||
s.repo.packageRefs = nil
|
s.repo.packageRefs = nil
|
||||||
_, err := NewSnapshotFromRepository("snap2", s.repo)
|
_, err := NewSnapshotFromRepository("snap2", s.repo)
|
||||||
c.Check(err, ErrorMatches, ".*not updated")
|
c.Check(err, ErrorMatches, ".*not updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SnapshotSuite) TestNewSnapshotFromPackageList(c *C) {
|
||||||
|
snap, _ := NewSnapshotFromRepository("snap1", s.repo)
|
||||||
|
|
||||||
|
snapshot := NewSnapshotFromPackageList("snap2", []*Snapshot{snap}, s.list, "Pulled")
|
||||||
|
c.Check(snapshot.Name, Equals, "snap2")
|
||||||
|
c.Check(snapshot.NumPackages(), Equals, 3)
|
||||||
|
c.Check(snapshot.SourceKind, Equals, "snapshot")
|
||||||
|
c.Check(snapshot.SourceIDs, DeepEquals, []string{snap.UUID})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SnapshotSuite) TestNewSnapshotFromRefList(c *C) {
|
||||||
|
snap, _ := NewSnapshotFromRepository("snap1", s.repo)
|
||||||
|
|
||||||
|
snapshot := NewSnapshotFromRefList("snap2", []*Snapshot{snap}, s.reflist, "Merged")
|
||||||
|
c.Check(snapshot.Name, Equals, "snap2")
|
||||||
|
c.Check(snapshot.NumPackages(), Equals, 3)
|
||||||
|
c.Check(snapshot.SourceKind, Equals, "snapshot")
|
||||||
|
c.Check(snapshot.SourceIDs, DeepEquals, []string{snap.UUID})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SnapshotSuite) TestKey(c *C) {
|
func (s *SnapshotSuite) TestKey(c *C) {
|
||||||
snapshot, _ := NewSnapshotFromRepository("snap1", s.repo)
|
snapshot, _ := NewSnapshotFromRepository("snap1", s.repo)
|
||||||
c.Assert(len(snapshot.Key()), Equals, 37)
|
c.Assert(len(snapshot.Key()), Equals, 37)
|
||||||
@@ -81,7 +103,7 @@ func (s *SnapshotCollectionSuite) TearDownTest(c *C) {
|
|||||||
s.db.Close()
|
s.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SnapshotCollectionSuite) TestAddByName(c *C) {
|
func (s *SnapshotCollectionSuite) TestAddByNameByUUID(c *C) {
|
||||||
snapshot, err := s.collection.ByName("snap1")
|
snapshot, err := s.collection.ByName("snap1")
|
||||||
c.Assert(err, ErrorMatches, "*.not found")
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
@@ -98,6 +120,10 @@ func (s *SnapshotCollectionSuite) TestAddByName(c *C) {
|
|||||||
snapshot, err = collection.ByName("snap1")
|
snapshot, err = collection.ByName("snap1")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(snapshot.String(), Equals, s.snapshot1.String())
|
c.Assert(snapshot.String(), Equals, s.snapshot1.String())
|
||||||
|
|
||||||
|
snapshot, err = collection.ByUUID(s.snapshot1.UUID)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(snapshot.String(), Equals, s.snapshot1.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SnapshotCollectionSuite) TestUpdateLoadComplete(c *C) {
|
func (s *SnapshotCollectionSuite) TestUpdateLoadComplete(c *C) {
|
||||||
@@ -112,7 +138,7 @@ func (s *SnapshotCollectionSuite) TestUpdateLoadComplete(c *C) {
|
|||||||
c.Assert(snapshot.NumPackages(), Equals, 3)
|
c.Assert(snapshot.NumPackages(), Equals, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SnapshotCollectionSuite) TestForEach(c *C) {
|
func (s *SnapshotCollectionSuite) TestForEachAndLen(c *C) {
|
||||||
s.collection.Add(s.snapshot1)
|
s.collection.Add(s.snapshot1)
|
||||||
s.collection.Add(s.snapshot2)
|
s.collection.Add(s.snapshot2)
|
||||||
|
|
||||||
@@ -124,6 +150,8 @@ func (s *SnapshotCollectionSuite) TestForEach(c *C) {
|
|||||||
c.Assert(count, Equals, 2)
|
c.Assert(count, Equals, 2)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
c.Check(s.collection.Len(), Equals, 2)
|
||||||
|
|
||||||
e := errors.New("d")
|
e := errors.New("d")
|
||||||
err = s.collection.ForEach(func(*Snapshot) error {
|
err = s.collection.ForEach(func(*Snapshot) error {
|
||||||
return e
|
return e
|
||||||
|
|||||||
Vendored
+271
@@ -0,0 +1,271 @@
|
|||||||
|
package debian
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Using documentation from: http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
|
||||||
|
|
||||||
|
// CompareVersions compares two package versions
|
||||||
|
func CompareVersions(ver1, ver2 string) int {
|
||||||
|
e1, u1, d1 := parseVersion(ver1)
|
||||||
|
e2, u2, d2 := parseVersion(ver2)
|
||||||
|
|
||||||
|
r := compareVersionPart(e1, e2)
|
||||||
|
if r != 0 {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
r = compareVersionPart(u1, u2)
|
||||||
|
if r != 0 {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
return compareVersionPart(d1, d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseVersions breaks down full version to components (possibly empty)
|
||||||
|
func parseVersion(ver string) (epoch, upstream, debian string) {
|
||||||
|
i := strings.LastIndex(ver, "-")
|
||||||
|
if i != -1 {
|
||||||
|
debian, ver = ver[i+1:], ver[:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
i = strings.Index(ver, ":")
|
||||||
|
if i != -1 {
|
||||||
|
epoch, ver = ver[:i], ver[i+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream = ver
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareLexicographic compares in "Debian lexicographic" way, see below compareVersionPart for details
|
||||||
|
func compareLexicographic(s1, s2 string) int {
|
||||||
|
i := 0
|
||||||
|
l1, l2 := len(s1), len(s2)
|
||||||
|
|
||||||
|
for {
|
||||||
|
if i == l1 && i == l2 {
|
||||||
|
// s1 equal to s2
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == l2 {
|
||||||
|
// s1 is longer than s2
|
||||||
|
if s1[i] == '~' {
|
||||||
|
return -1 // s1 < s2
|
||||||
|
}
|
||||||
|
return 1 // s1 > s2
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == l1 {
|
||||||
|
// s2 is longer than s1
|
||||||
|
if s2[i] == '~' {
|
||||||
|
return 1 // s1 > s2
|
||||||
|
}
|
||||||
|
return -1 // s1 < s2
|
||||||
|
}
|
||||||
|
|
||||||
|
if s1[i] == s2[i] {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s1[i] == '~' {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if s2[i] == '~' {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c1, c2 := unicode.IsLetter(rune(s1[i])), unicode.IsLetter(rune(s2[i]))
|
||||||
|
if c1 && !c2 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if !c1 && c2 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if s1[i] < s2[i] {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareVersionPart compares parts of full version
|
||||||
|
//
|
||||||
|
// From Debian Policy Manual:
|
||||||
|
//
|
||||||
|
// "The strings are compared from left to right.
|
||||||
|
//
|
||||||
|
// First the initial part of each string consisting entirely of non-digit characters is
|
||||||
|
// determined. These two parts (one of which may be empty) are compared lexically. If a
|
||||||
|
// difference is found it is returned. The lexical comparison is a comparison of ASCII values
|
||||||
|
// modified so that all the letters sort earlier than all the non-letters and so that a tilde
|
||||||
|
// sorts before anything, even the end of a part. For example, the following parts are in sorted
|
||||||
|
// order from earliest to latest: ~~, ~~a, ~, the empty part.
|
||||||
|
//
|
||||||
|
// Then the initial part of the remainder of each string which consists entirely of digit
|
||||||
|
// characters is determined. The numerical values of these two parts are compared, and any difference
|
||||||
|
// found is returned as the result of the comparison. For these purposes an empty string (which can only occur at
|
||||||
|
// the end of one or both version strings being compared) counts as zero.
|
||||||
|
|
||||||
|
// These two steps (comparing and removing initial non-digit strings and initial digit strings) are
|
||||||
|
// repeated until a difference is found or both strings are exhausted."
|
||||||
|
func compareVersionPart(part1, part2 string) int {
|
||||||
|
i1, i2 := 0, 0
|
||||||
|
l1, l2 := len(part1), len(part2)
|
||||||
|
|
||||||
|
for {
|
||||||
|
j1, j2 := i1, i2
|
||||||
|
for j1 < l1 && !unicode.IsDigit(rune(part1[j1])) {
|
||||||
|
j1++
|
||||||
|
}
|
||||||
|
|
||||||
|
for j2 < l2 && !unicode.IsDigit(rune(part2[j2])) {
|
||||||
|
j2++
|
||||||
|
}
|
||||||
|
|
||||||
|
s1, s2 := part1[i1:j1], part2[i2:j2]
|
||||||
|
r := compareLexicographic(s1, s2)
|
||||||
|
if r != 0 {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
i1, i2 = j1, j2
|
||||||
|
|
||||||
|
for j1 < l1 && unicode.IsDigit(rune(part1[j1])) {
|
||||||
|
j1++
|
||||||
|
}
|
||||||
|
|
||||||
|
for j2 < l2 && unicode.IsDigit(rune(part2[j2])) {
|
||||||
|
j2++
|
||||||
|
}
|
||||||
|
|
||||||
|
s1, s2 = part1[i1:j1], part2[i2:j2]
|
||||||
|
n1, _ := strconv.Atoi(s1)
|
||||||
|
n2, _ := strconv.Atoi(s2)
|
||||||
|
|
||||||
|
if n1 < n2 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if n1 > n2 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
i1, i2 = j1, j2
|
||||||
|
|
||||||
|
if i1 == l1 && i2 == l2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version relations
|
||||||
|
const (
|
||||||
|
VersionDontCare = iota
|
||||||
|
VersionLess
|
||||||
|
VersionLessOrEqual
|
||||||
|
VersionEqual
|
||||||
|
VersionGreaterOrEqual
|
||||||
|
VersionGreater
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dependency is a parsed version of Debian dependency to package
|
||||||
|
type Dependency struct {
|
||||||
|
Pkg string
|
||||||
|
Relation int
|
||||||
|
Version string
|
||||||
|
Architecture string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash calculates some predefined unique ID of Dependency
|
||||||
|
func (d *Dependency) Hash() string {
|
||||||
|
return fmt.Sprintf("%s:%s:%d:%s", d.Architecture, d.Pkg, d.Relation, d.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String produces human-readable representation
|
||||||
|
func (d *Dependency) String() string {
|
||||||
|
var rel string
|
||||||
|
switch d.Relation {
|
||||||
|
case VersionEqual:
|
||||||
|
rel = "="
|
||||||
|
case VersionGreater:
|
||||||
|
rel = ">>"
|
||||||
|
case VersionLess:
|
||||||
|
rel = "<<"
|
||||||
|
case VersionGreaterOrEqual:
|
||||||
|
rel = ">="
|
||||||
|
case VersionLessOrEqual:
|
||||||
|
rel = "<="
|
||||||
|
case VersionDontCare:
|
||||||
|
return fmt.Sprintf("%s [%s]", d.Pkg, d.Architecture)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s (%s %s) [%s]", d.Pkg, rel, d.Version, d.Architecture)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDependencyVariants parses dependencies in format "pkg (>= 1.35) | other-package"
|
||||||
|
func ParseDependencyVariants(variants string) (l []Dependency, err error) {
|
||||||
|
parts := strings.Split(variants, "|")
|
||||||
|
l = make([]Dependency, len(parts))
|
||||||
|
|
||||||
|
for i, part := range parts {
|
||||||
|
l[i], err = ParseDependency(strings.TrimSpace(part))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDependency parses dependency in format "pkg (>= 1.35)" into parts
|
||||||
|
func ParseDependency(dep string) (d Dependency, err error) {
|
||||||
|
if !strings.HasSuffix(dep, ")") {
|
||||||
|
d.Pkg = strings.TrimSpace(dep)
|
||||||
|
d.Relation = VersionDontCare
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
i := strings.Index(dep, "(")
|
||||||
|
if i == -1 {
|
||||||
|
err = fmt.Errorf("unable to parse dependency: %s", dep)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Pkg = strings.TrimSpace(dep[0:i])
|
||||||
|
|
||||||
|
rel := dep[i+1 : i+2]
|
||||||
|
if dep[i+2] == '>' || dep[i+2] == '<' || dep[i+2] == '=' {
|
||||||
|
rel += dep[i+2 : i+3]
|
||||||
|
d.Version = strings.TrimSpace(dep[i+3 : len(dep)-1])
|
||||||
|
} else {
|
||||||
|
d.Version = strings.TrimSpace(dep[i+2 : len(dep)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
switch rel {
|
||||||
|
case "<", "<=":
|
||||||
|
d.Relation = VersionLessOrEqual
|
||||||
|
case ">", ">=":
|
||||||
|
d.Relation = VersionGreaterOrEqual
|
||||||
|
case "<<":
|
||||||
|
d.Relation = VersionLess
|
||||||
|
case ">>":
|
||||||
|
d.Relation = VersionGreater
|
||||||
|
case "=":
|
||||||
|
d.Relation = VersionEqual
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("relation unknown: %s", rel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
Vendored
+186
@@ -0,0 +1,186 @@
|
|||||||
|
package debian
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "launchpad.net/gocheck"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VersionSuite struct {
|
||||||
|
stanza Stanza
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Suite(&VersionSuite{})
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestParseVersion(c *C) {
|
||||||
|
e, u, d := parseVersion("1.3.4")
|
||||||
|
c.Check([]string{e, u, d}, DeepEquals, []string{"", "1.3.4", ""})
|
||||||
|
|
||||||
|
e, u, d = parseVersion("4:1.3:4")
|
||||||
|
c.Check([]string{e, u, d}, DeepEquals, []string{"4", "1.3:4", ""})
|
||||||
|
|
||||||
|
e, u, d = parseVersion("1.3.4-1")
|
||||||
|
c.Check([]string{e, u, d}, DeepEquals, []string{"", "1.3.4", "1"})
|
||||||
|
|
||||||
|
e, u, d = parseVersion("1.3-pre4-1")
|
||||||
|
c.Check([]string{e, u, d}, DeepEquals, []string{"", "1.3-pre4", "1"})
|
||||||
|
|
||||||
|
e, u, d = parseVersion("4:1.3-pre4-1")
|
||||||
|
c.Check([]string{e, u, d}, DeepEquals, []string{"4", "1.3-pre4", "1"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestCompareLexicographic(c *C) {
|
||||||
|
c.Check(compareLexicographic("", ""), Equals, 0)
|
||||||
|
c.Check(compareLexicographic("pre", "pre"), Equals, 0)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("pr", "pre"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("pre", "pr"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("pra", "prb"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("prb", "pra"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("prx", "pr+"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("pr+", "prx"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("pr~", "pra"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("pra", "pr~"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("~~", "~~a"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("~~a", "~"), Equals, -1)
|
||||||
|
c.Check(compareLexicographic("~", ""), Equals, -1)
|
||||||
|
|
||||||
|
c.Check(compareLexicographic("~~a", "~~"), Equals, 1)
|
||||||
|
c.Check(compareLexicographic("~", "~~a"), Equals, 1)
|
||||||
|
c.Check(compareLexicographic("", "~"), Equals, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestCompareVersionPart(c *C) {
|
||||||
|
c.Check(compareVersionPart("", ""), Equals, 0)
|
||||||
|
c.Check(compareVersionPart("pre", "pre"), Equals, 0)
|
||||||
|
c.Check(compareVersionPart("12", "12"), Equals, 0)
|
||||||
|
c.Check(compareVersionPart("1.3.5", "1.3.5"), Equals, 0)
|
||||||
|
c.Check(compareVersionPart("1.3.5-pre1", "1.3.5-pre1"), Equals, 0)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("1.0~beta1~svn1245", "1.0~beta1"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("1.0~beta1", "1.0"), Equals, -1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("1.0~beta1", "1.0~beta1~svn1245"), Equals, 1)
|
||||||
|
c.Check(compareVersionPart("1.0", "1.0~beta1"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("1.pr", "1.pre"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("1.pre", "1.pr"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("1.pra", "1.prb"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("1.prb", "1.pra"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("3.prx", "3.pr+"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("3.pr+", "3.prx"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("3.pr~", "3.pra"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("3.pra", "3.pr~"), Equals, 1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("2~~", "2~~a"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("2~~a", "2~"), Equals, -1)
|
||||||
|
c.Check(compareVersionPart("2~", "2"), Equals, -1)
|
||||||
|
|
||||||
|
c.Check(compareVersionPart("2~~a", "2~~"), Equals, 1)
|
||||||
|
c.Check(compareVersionPart("2~", "2~~a"), Equals, 1)
|
||||||
|
c.Check(compareVersionPart("2", "2~"), Equals, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestCompareVersions(c *C) {
|
||||||
|
c.Check(CompareVersions("3:1.0~beta1~svn1245-1", "3:1.0~beta1~svn1245-1"), Equals, 0)
|
||||||
|
|
||||||
|
c.Check(CompareVersions("1:1.0~beta1~svn1245-1", "3:1.0~beta1~svn1245-1"), Equals, -1)
|
||||||
|
c.Check(CompareVersions("1:1.0~beta1~svn1245-1", "1.0~beta1~svn1245-1"), Equals, 1)
|
||||||
|
c.Check(CompareVersions("1.0~beta1~svn1245-1", "1.0~beta1~svn1245-2"), Equals, -1)
|
||||||
|
c.Check(CompareVersions("3:1.0~beta1~svn1245-1", "3:1.0~beta1-1"), Equals, -1)
|
||||||
|
|
||||||
|
c.Check(CompareVersions("1.0~beta1~svn1245", "1.0~beta1"), Equals, -1)
|
||||||
|
c.Check(CompareVersions("1.0~beta1", "1.0"), Equals, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestParseDependency(c *C) {
|
||||||
|
d, e := ParseDependency("dpkg (>= 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionGreaterOrEqual)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg(>>1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionGreater)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg (> 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionGreaterOrEqual)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg (< 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionLessOrEqual)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg (= 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionEqual)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg (<< 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionLess)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg(>>1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionGreater)
|
||||||
|
c.Check(d.Version, Equals, "1.6")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg ")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(d.Pkg, Equals, "dpkg")
|
||||||
|
c.Check(d.Relation, Equals, VersionDontCare)
|
||||||
|
c.Check(d.Version, Equals, "")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg(==1.6)")
|
||||||
|
c.Check(e, ErrorMatches, "relation unknown.*")
|
||||||
|
|
||||||
|
d, e = ParseDependency("dpkg==1.6)")
|
||||||
|
c.Check(e, ErrorMatches, "unable to parse.*")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestParseDependencyVariants(c *C) {
|
||||||
|
l, e := ParseDependencyVariants("dpkg (>= 1.6)")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(l, HasLen, 1)
|
||||||
|
c.Check(l[0].Pkg, Equals, "dpkg")
|
||||||
|
c.Check(l[0].Relation, Equals, VersionGreaterOrEqual)
|
||||||
|
c.Check(l[0].Version, Equals, "1.6")
|
||||||
|
|
||||||
|
l, e = ParseDependencyVariants("dpkg (>= 1.6) | mailer-agent")
|
||||||
|
c.Check(e, IsNil)
|
||||||
|
c.Check(l, HasLen, 2)
|
||||||
|
c.Check(l[0].Pkg, Equals, "dpkg")
|
||||||
|
c.Check(l[0].Relation, Equals, VersionGreaterOrEqual)
|
||||||
|
c.Check(l[0].Version, Equals, "1.6")
|
||||||
|
c.Check(l[1].Pkg, Equals, "mailer-agent")
|
||||||
|
c.Check(l[1].Relation, Equals, VersionDontCare)
|
||||||
|
|
||||||
|
_, e = ParseDependencyVariants("dpkg(==1.6)")
|
||||||
|
c.Check(e, ErrorMatches, "relation unknown.*")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestDependencyString(c *C) {
|
||||||
|
d, _ := ParseDependency("dpkg(>>1.6)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.String(), Equals, "dpkg (>> 1.6) [i386]")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.String(), Equals, "dpkg [i386]")
|
||||||
|
}
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/gonuts/commander"
|
"github.com/gonuts/commander"
|
||||||
"github.com/gonuts/flag"
|
"github.com/gonuts/flag"
|
||||||
"github.com/smira/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/smira/aptly/debian"
|
"github.com/smira/aptly/debian"
|
||||||
"github.com/smira/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// aptly version
|
// aptly version
|
||||||
const Version = "0.1"
|
const Version = "0.2"
|
||||||
|
|
||||||
var cmd *commander.Command
|
var cmd *commander.Command
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ func init() {
|
|||||||
UsageLine: os.Args[0],
|
UsageLine: os.Args[0],
|
||||||
Short: "Debian repository management tool",
|
Short: "Debian repository management tool",
|
||||||
Long: `
|
Long: `
|
||||||
aptly allows to create partial and full mirrors of remote
|
aptly is a tool to create partial and full mirrors of remote
|
||||||
repositories, filter them, merge, upgrade individual packages,
|
repositories, filter them, merge, upgrade individual packages,
|
||||||
take snapshots and publish them back as Debian repositories.`,
|
take snapshots and publish them back as Debian repositories.`,
|
||||||
Flag: *flag.NewFlagSet("aptly", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly", flag.ExitOnError),
|
||||||
@@ -32,18 +33,30 @@ take snapshots and publish them back as Debian repositories.`,
|
|||||||
makeCmdVersion(),
|
makeCmdVersion(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.Flag.Bool("dep-follow-suggests", false, "when processing dependencies, follow Suggests")
|
||||||
|
cmd.Flag.Bool("dep-follow-recommends", false, "when processing dependencies, follow Recommends")
|
||||||
|
cmd.Flag.Bool("dep-follow-all-variants", false, "when processing dependencies, follow a & b if depdency is 'a|b'")
|
||||||
|
cmd.Flag.String("architectures", "", "list of architectures to consider during (comma-separated), default to all available")
|
||||||
}
|
}
|
||||||
|
|
||||||
var context struct {
|
var context struct {
|
||||||
downloader utils.Downloader
|
downloader utils.Downloader
|
||||||
database database.Storage
|
database database.Storage
|
||||||
packageRepository *debian.Repository
|
packageRepository *debian.Repository
|
||||||
|
dependencyOptions int
|
||||||
|
architecturesList []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatal(err error) {
|
||||||
|
fmt.Printf("ERROR: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := cmd.Flag.Parse(os.Args[1:])
|
err := cmd.Flag.Parse(os.Args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%s", err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
configLocations := []string{
|
configLocations := []string{
|
||||||
@@ -56,28 +69,46 @@ func main() {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
fatal(fmt.Errorf("error loading config file %s: %s", configLocation, err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Config file not found, creating default config at %s\n\n", configLocations[0])
|
fmt.Printf("Config file not found, creating default config at %s\n\n", configLocations[0])
|
||||||
utils.SaveConfig(configLocations[0], &utils.Config)
|
utils.SaveConfig(configLocations[0], &utils.Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.dependencyOptions = 0
|
||||||
|
if utils.Config.DepFollowSuggests || cmd.Flag.Lookup("dep-follow-suggests").Value.Get().(bool) {
|
||||||
|
context.dependencyOptions |= debian.DepFollowSuggests
|
||||||
|
}
|
||||||
|
if utils.Config.DepFollowRecommends || cmd.Flag.Lookup("dep-follow-recommends").Value.Get().(bool) {
|
||||||
|
context.dependencyOptions |= debian.DepFollowRecommends
|
||||||
|
}
|
||||||
|
if utils.Config.DepFollowAllVariants || cmd.Flag.Lookup("dep-follow-all-variants").Value.Get().(bool) {
|
||||||
|
context.dependencyOptions |= debian.DepFollowAllVariants
|
||||||
|
}
|
||||||
|
|
||||||
|
context.architecturesList = utils.Config.Architectures
|
||||||
|
optionArchitectures := cmd.Flag.Lookup("architectures").Value.String()
|
||||||
|
if optionArchitectures != "" {
|
||||||
|
context.architecturesList = strings.Split(optionArchitectures, ",")
|
||||||
|
}
|
||||||
|
|
||||||
context.downloader = utils.NewDownloader(utils.Config.DownloadConcurrency)
|
context.downloader = utils.NewDownloader(utils.Config.DownloadConcurrency)
|
||||||
defer context.downloader.Shutdown()
|
defer context.downloader.Shutdown()
|
||||||
|
|
||||||
// TODO: configure DB dir
|
|
||||||
context.database, err = database.OpenDB(filepath.Join(utils.Config.RootDir, "db"))
|
context.database, err = database.OpenDB(filepath.Join(utils.Config.RootDir, "db"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("can't open database: %s", err)
|
fatal(fmt.Errorf("can't open database: %s", err))
|
||||||
}
|
}
|
||||||
defer context.database.Close()
|
defer context.database.Close()
|
||||||
|
|
||||||
// TODO:configure pool dir
|
|
||||||
context.packageRepository = debian.NewRepository(utils.Config.RootDir)
|
context.packageRepository = debian.NewRepository(utils.Config.RootDir)
|
||||||
|
|
||||||
err = cmd.Dispatch(os.Args[1:])
|
err = cmd.Dispatch(cmd.Flag.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%s", err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
System test for aptly
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
aptly -architectures=i386,amd64 mirror create wheezy-main http://mirror.yandex.ru/debian/ wheezy main
|
||||||
|
aptly -architectures=i386,amd64 mirror create wheezy-contrib http://mirror.yandex.ru/debian/ wheezy contrib
|
||||||
|
aptly -architectures=i386,amd64 mirror create wheezy-non-free http://mirror.yandex.ru/debian/ wheezy non-free
|
||||||
|
aptly -architectures=i386,amd64 mirror create wheezy-updates http://mirror.yandex.ru/debian/ wheezy-updates
|
||||||
|
aptly -architectures=i386,amd64 mirror create wheezy-backports http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
|
||||||
|
aptly mirror update wheezy-main
|
||||||
|
aptly mirror update wheezy-contrib
|
||||||
|
aptly mirror update wheezy-non-free
|
||||||
|
aptly mirror update wheezy-updates
|
||||||
|
aptly mirror update wheezy-backports
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
"""
|
||||||
|
Test library.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import difflib
|
||||||
|
import inspect
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import shutil
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTest(object):
|
||||||
|
"""
|
||||||
|
Base class for all tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
longTest = False
|
||||||
|
fixturePool = False
|
||||||
|
fixtureDB = False
|
||||||
|
|
||||||
|
expectedCode = 0
|
||||||
|
configFile = {
|
||||||
|
"rootDir": "%s/.aptly" % os.environ["HOME"],
|
||||||
|
"downloadConcurrency": 4,
|
||||||
|
"architectures": [],
|
||||||
|
"dependencyFollowSuggests": False,
|
||||||
|
"dependencyFollowRecommends": False,
|
||||||
|
"dependencyFollowAllVariants": False
|
||||||
|
}
|
||||||
|
configOverride = {}
|
||||||
|
|
||||||
|
fixtureDBDir = os.path.join(os.environ["HOME"], "aptly-fixture-db")
|
||||||
|
fixturePoolDir = os.path.join(os.environ["HOME"], "aptly-fixture-pool")
|
||||||
|
|
||||||
|
outputMatchPrepare = None
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
self.prepare()
|
||||||
|
self.run()
|
||||||
|
self.check()
|
||||||
|
|
||||||
|
def prepare_remove_all(self):
|
||||||
|
if os.path.exists(os.path.join(os.environ["HOME"], ".aptly")):
|
||||||
|
shutil.rmtree(os.path.join(os.environ["HOME"], ".aptly"))
|
||||||
|
if os.path.exists(os.path.join(os.environ["HOME"], ".aptly.conf")):
|
||||||
|
os.remove(os.path.join(os.environ["HOME"], ".aptly.conf"))
|
||||||
|
|
||||||
|
def prepare_default_config(self):
|
||||||
|
cfg = self.configFile.copy()
|
||||||
|
cfg.update(**self.configOverride)
|
||||||
|
f = open(os.path.join(os.environ["HOME"], ".aptly.conf"), "w")
|
||||||
|
f.write(json.dumps(cfg))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def fixture_available(self):
|
||||||
|
if self.fixturePool and not os.path.exists(self.fixturePoolDir):
|
||||||
|
return False
|
||||||
|
if self.fixtureDB and not os.path.exists(self.fixtureDBDir):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def prepare_fixture(self):
|
||||||
|
if self.fixturePool:
|
||||||
|
os.makedirs(os.path.join(os.environ["HOME"], ".aptly"), 0755)
|
||||||
|
os.symlink(self.fixturePoolDir, os.path.join(os.environ["HOME"], ".aptly", "pool"))
|
||||||
|
|
||||||
|
if self.fixtureDB:
|
||||||
|
shutil.copytree(self.fixtureDBDir, os.path.join(os.environ["HOME"], ".aptly", "db"))
|
||||||
|
|
||||||
|
if hasattr(self, "fixtureCmds"):
|
||||||
|
for cmd in self.fixtureCmds:
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.output = self.output_processor(self.run_cmd(self.runCmd, self.expectedCode))
|
||||||
|
|
||||||
|
def run_cmd(self, command, expected_code=0):
|
||||||
|
try:
|
||||||
|
proc = subprocess.Popen(shlex.split(command), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
|
||||||
|
output, _ = proc.communicate()
|
||||||
|
if proc.returncode != expected_code:
|
||||||
|
raise Exception("exit code %d != %d (output: %s)" % (proc.returncode, expected_code, output))
|
||||||
|
return output
|
||||||
|
except Exception, e:
|
||||||
|
raise Exception("Running command %s failed: %s" % (command, str(e)))
|
||||||
|
|
||||||
|
def gold_processor(self, gold):
|
||||||
|
return gold
|
||||||
|
|
||||||
|
def output_processor(self, output):
|
||||||
|
return output
|
||||||
|
|
||||||
|
def expand_environ(self, gold):
|
||||||
|
return string.Template(gold).substitute(os.environ)
|
||||||
|
|
||||||
|
def get_gold(self, gold_name="gold"):
|
||||||
|
gold = os.path.join(os.path.dirname(inspect.getsourcefile(self.__class__)), self.__class__.__name__ + "_" + gold_name)
|
||||||
|
return self.gold_processor(open(gold, "r").read())
|
||||||
|
|
||||||
|
def check_output(self):
|
||||||
|
self.verify_match(self.get_gold(), self.output, match_prepare=self.outputMatchPrepare)
|
||||||
|
|
||||||
|
def check_cmd_output(self, command, gold_name, match_prepare=None):
|
||||||
|
self.verify_match(self.get_gold(gold_name), self.run_cmd(command), match_prepare)
|
||||||
|
|
||||||
|
def verify_match(self, a, b, match_prepare=None):
|
||||||
|
if match_prepare is not None:
|
||||||
|
a = match_prepare(a)
|
||||||
|
b = match_prepare(b)
|
||||||
|
|
||||||
|
if a != b:
|
||||||
|
diff = "".join(difflib.unified_diff([l + "\n" for l in a.split("\n")], [l + "\n" for l in b.split("\n")]))
|
||||||
|
|
||||||
|
raise Exception("content doesn't match:\n" + diff + "\n")
|
||||||
|
|
||||||
|
def check_file(self):
|
||||||
|
self.verify_match(self.get_gold(), open(self.checkedFile, "r").read())
|
||||||
|
|
||||||
|
check = check_output
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
self.prepare_remove_all()
|
||||||
|
self.prepare_default_config()
|
||||||
|
self.prepare_fixture()
|
||||||
Executable
+69
@@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/local/bin/python
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
import inspect
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
try:
|
||||||
|
from termcolor import colored
|
||||||
|
except ImportError:
|
||||||
|
def colored(s, **kwargs):
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def run(include_long_tests=False):
|
||||||
|
"""
|
||||||
|
Run system test.
|
||||||
|
"""
|
||||||
|
tests = glob.glob("t*_*")
|
||||||
|
fails = []
|
||||||
|
numTests = numFailed = numSkipped = 0
|
||||||
|
|
||||||
|
for test in tests:
|
||||||
|
|
||||||
|
testModule = importlib.import_module(test)
|
||||||
|
|
||||||
|
for name in dir(testModule):
|
||||||
|
o = getattr(testModule, name)
|
||||||
|
|
||||||
|
if not (inspect.isclass(o) and issubclass(o, BaseTest) and o is not BaseTest):
|
||||||
|
continue
|
||||||
|
|
||||||
|
t = o()
|
||||||
|
if t.longTest and not include_long_tests or not t.fixture_available():
|
||||||
|
numSkipped += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
numTests += 1
|
||||||
|
|
||||||
|
sys.stdout.write("%s:%s... " % (test, o.__name__))
|
||||||
|
|
||||||
|
try:
|
||||||
|
t.test()
|
||||||
|
except BaseException, e:
|
||||||
|
numFailed += 1
|
||||||
|
fails.append((test, t, e, testModule))
|
||||||
|
sys.stdout.write(colored("FAIL\n", color="red"))
|
||||||
|
else:
|
||||||
|
sys.stdout.write(colored("OK\n", color="green"))
|
||||||
|
|
||||||
|
print "TESTS: %d SUCCESS: %d FAIL: %d SKIP: %d" % (numTests, numTests - numFailed, numFailed, numSkipped)
|
||||||
|
|
||||||
|
if len(fails) > 0:
|
||||||
|
print "\nFAILURES (%d):" % (len(fails), )
|
||||||
|
|
||||||
|
for (test, t, e, testModule) in fails:
|
||||||
|
print "%s:%s %s" % (test, t.__class__.__name__, testModule.__doc__.strip() + ": " + t.__doc__.strip())
|
||||||
|
print "ERROR: %s" % (e, )
|
||||||
|
print "=" * 60
|
||||||
|
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
os.chdir(os.path.realpath(os.path.dirname(sys.argv[0])))
|
||||||
|
include_long_tests = len(sys.argv) > 1 and sys.argv[1] == "--long"
|
||||||
|
run(include_long_tests)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
aptly version: 0.2
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
"""
|
||||||
|
Test aptly version
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class VersionTest(BaseTest):
|
||||||
|
"""
|
||||||
|
version should match
|
||||||
|
"""
|
||||||
|
|
||||||
|
runCmd = "aptly version"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: error loading config file ${HOME}/.aptly.conf: invalid character 's' looking for beginning of object key string
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"rootDir": "${HOME}/.aptly",
|
||||||
|
"downloadConcurrency": 4,
|
||||||
|
"architectures": [],
|
||||||
|
"dependencyFollowSuggests": false,
|
||||||
|
"dependencyFollowRecommends": false,
|
||||||
|
"dependencyFollowAllVariants": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""
|
||||||
|
Test config file
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class CreateConfigTest(BaseTest):
|
||||||
|
"""
|
||||||
|
new file is generated if missing
|
||||||
|
"""
|
||||||
|
runCmd = "aptly"
|
||||||
|
checkedFile = os.path.join(os.environ["HOME"], ".aptly.conf")
|
||||||
|
|
||||||
|
check = BaseTest.check_file
|
||||||
|
gold_processor = BaseTest.expand_environ
|
||||||
|
prepare = BaseTest.prepare_remove_all
|
||||||
|
|
||||||
|
|
||||||
|
class BadConfigTest(BaseTest):
|
||||||
|
"""
|
||||||
|
broken config file
|
||||||
|
"""
|
||||||
|
runCmd = "aptly"
|
||||||
|
expectedCode = 1
|
||||||
|
|
||||||
|
gold_processor = BaseTest.expand_environ
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
self.prepare_remove_all()
|
||||||
|
|
||||||
|
f = open(os.path.join(os.environ["HOME"], ".aptly.conf"), "w")
|
||||||
|
f.write("{some crap")
|
||||||
|
f.close()
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
aptly is a tool to create partial and full mirrors of remote
|
||||||
|
repositories, filter them, merge, upgrade individual packages,
|
||||||
|
take snapshots and publish them back as Debian repositories.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-architectures="": list of architectures to consider during (comma-separated), default to all available
|
||||||
|
-dep-follow-all-variants=false: when processing dependencies, follow a & b if depdency is 'a|b'
|
||||||
|
-dep-follow-recommends=false: when processing dependencies, follow Recommends
|
||||||
|
-dep-follow-suggests=false: when processing dependencies, follow Suggests
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
aptly - Debian repository management tool
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
mirror manage mirrors of remote repositories
|
||||||
|
publish manage published repositories
|
||||||
|
snapshot manage snapshots of repositories
|
||||||
|
version display version
|
||||||
|
|
||||||
|
Use "aptly help <command>" for more information about a command.
|
||||||
|
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-architectures="": list of architectures to consider during (comma-separated), default to all available
|
||||||
|
-dep-follow-all-variants=false: when processing dependencies, follow a & b if depdency is 'a|b'
|
||||||
|
-dep-follow-recommends=false: when processing dependencies, follow Recommends
|
||||||
|
-dep-follow-suggests=false: when processing dependencies, follow Suggests
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Usage: aptly mirror create <name> <archive url> <distribution> [<component1> ...]
|
||||||
|
|
||||||
|
Create records information about new mirror and fetches Release file (it doesn't download packages).
|
||||||
|
|
||||||
|
ex:
|
||||||
|
$ aptly mirror create wheezy-main http://mirror.yandex.ru/debian/ wheezy main
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Usage: aptly mirror create <name> <archive url> <distribution> [<component1> ...]
|
||||||
|
|
||||||
|
aptly mirror create - create new mirror of Debian repository
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
aptly mirror - manage mirrors of remote repositories
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
create create new mirror of Debian repository
|
||||||
|
list list mirrors of remote repositories
|
||||||
|
show show details about remote repository mirror
|
||||||
|
update update packages from remote mirror
|
||||||
|
|
||||||
|
Use "mirror help <command>" for more information about a command.
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
aptly mirror - manage mirrors of remote repositories
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
create create new mirror of Debian repository
|
||||||
|
list list mirrors of remote repositories
|
||||||
|
show show details about remote repository mirror
|
||||||
|
update update packages from remote mirror
|
||||||
|
|
||||||
|
Use "mirror help <command>" for more information about a command.
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""
|
||||||
|
Test help screens
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class MainTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly"
|
||||||
|
|
||||||
|
|
||||||
|
class MirrorTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror"
|
||||||
|
|
||||||
|
|
||||||
|
class MirrorCreateTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror create"
|
||||||
|
|
||||||
|
|
||||||
|
class MainHelpTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly help"
|
||||||
|
|
||||||
|
|
||||||
|
class MirrorHelpTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly help mirror"
|
||||||
|
|
||||||
|
|
||||||
|
class MirrorCreateHelpTest(BaseTest):
|
||||||
|
"""
|
||||||
|
main
|
||||||
|
"""
|
||||||
|
runCmd = "aptly help mirror create"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
|
||||||
|
Mirror [mirror1]: http://mirror.yandex.ru/debian/ wheezy successfully added.
|
||||||
|
You can run 'aptly mirror update mirror1' to download repository contents.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Name: mirror1
|
||||||
|
Archive Root URL: http://mirror.yandex.ru/debian/
|
||||||
|
Distribution: wheezy
|
||||||
|
Components: main, contrib, non-free
|
||||||
|
Architectures: amd64, armel, armhf, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, s390x, sparc
|
||||||
|
Last update: never
|
||||||
|
|
||||||
|
Information from release file:
|
||||||
|
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
|
||||||
|
Codename: wheezy
|
||||||
|
Components: main contrib non-free
|
||||||
|
Date: Sat, 14 Dec 2013 10:51:30 UTC
|
||||||
|
Description: Debian 7.3 Released 14 December 2013
|
||||||
|
|
||||||
|
Label: Debian
|
||||||
|
Origin: Debian
|
||||||
|
Suite: stable
|
||||||
|
Version: 7.3
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
|
||||||
|
Mirror [mirror2]: http://mirror.yandex.ru/debian/ wheezy successfully added.
|
||||||
|
You can run 'aptly mirror update mirror2' to download repository contents.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Name: mirror2
|
||||||
|
Archive Root URL: http://mirror.yandex.ru/debian/
|
||||||
|
Distribution: wheezy
|
||||||
|
Components: main
|
||||||
|
Architectures: amd64, armel, armhf, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, s390x, sparc
|
||||||
|
Last update: never
|
||||||
|
|
||||||
|
Information from release file:
|
||||||
|
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
|
||||||
|
Codename: wheezy
|
||||||
|
Components: main contrib non-free
|
||||||
|
Date: Sat, 14 Dec 2013 10:51:30 UTC
|
||||||
|
Description: Debian 7.3 Released 14 December 2013
|
||||||
|
|
||||||
|
Label: Debian
|
||||||
|
Origin: Debian
|
||||||
|
Suite: stable
|
||||||
|
Version: 7.3
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
|
||||||
|
Mirror [mirror3]: http://mirror.yandex.ru/debian/ wheezy successfully added.
|
||||||
|
You can run 'aptly mirror update mirror3' to download repository contents.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Name: mirror3
|
||||||
|
Archive Root URL: http://mirror.yandex.ru/debian/
|
||||||
|
Distribution: wheezy
|
||||||
|
Components: main, contrib
|
||||||
|
Architectures: i386, amd64
|
||||||
|
Last update: never
|
||||||
|
|
||||||
|
Information from release file:
|
||||||
|
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
|
||||||
|
Codename: wheezy
|
||||||
|
Components: main contrib non-free
|
||||||
|
Date: Sat, 14 Dec 2013 10:51:30 UTC
|
||||||
|
Description: Debian 7.3 Released 14 December 2013
|
||||||
|
|
||||||
|
Label: Debian
|
||||||
|
Origin: Debian
|
||||||
|
Suite: stable
|
||||||
|
Version: 7.3
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
ERROR: unable to fetch mirror: component life not available in repo [mirror4]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
ERROR: unable to fetch mirror: architecture nano68 not available in repo [mirror5]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/suslik/Release...
|
||||||
|
ERROR: unable to fetch mirror: HTTP code 404 while fetching http://mirror.yandex.ru/debian/dists/suslik/Release
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
|
||||||
|
Mirror [mirror7]: http://mirror.yandex.ru/debian/ wheezy successfully added.
|
||||||
|
You can run 'aptly mirror update mirror7' to download repository contents.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Name: mirror7
|
||||||
|
Archive Root URL: http://mirror.yandex.ru/debian/
|
||||||
|
Distribution: wheezy
|
||||||
|
Components: main, contrib
|
||||||
|
Architectures: i386, amd64
|
||||||
|
Last update: never
|
||||||
|
|
||||||
|
Information from release file:
|
||||||
|
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
|
||||||
|
Codename: wheezy
|
||||||
|
Components: main contrib non-free
|
||||||
|
Date: Sat, 14 Dec 2013 10:51:30 UTC
|
||||||
|
Description: Debian 7.3 Released 14 December 2013
|
||||||
|
|
||||||
|
Label: Debian
|
||||||
|
Origin: Debian
|
||||||
|
Suite: stable
|
||||||
|
Version: 7.3
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release...
|
||||||
|
ERROR: unable to add mirror: mirror with name mirror8 already exists
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
List of mirrors:
|
||||||
|
* [mirror1]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
* [mirror2]: http://mirror.yandex.ru/debian/ squeeze
|
||||||
|
* [mirror3]: http://mirror.yandex.ru/debian/ squeeze
|
||||||
|
|
||||||
|
To get more information about mirror, run `aptly mirror show <name>`.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
No mirrors found, create one with `aptly mirror create ...`.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Name: mirror1
|
||||||
|
Archive Root URL: http://mirror.yandex.ru/debian/
|
||||||
|
Distribution: wheezy
|
||||||
|
Components: main, contrib, non-free
|
||||||
|
Architectures: amd64, armel, armhf, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, s390x, sparc
|
||||||
|
Last update: never
|
||||||
|
|
||||||
|
Information from release file:
|
||||||
|
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
|
||||||
|
Codename: wheezy
|
||||||
|
Components: main contrib non-free
|
||||||
|
Date: Sat, 14 Dec 2013 10:51:30 UTC
|
||||||
|
Description: Debian 7.3 Released 14 December 2013
|
||||||
|
|
||||||
|
Label: Debian
|
||||||
|
Origin: Debian
|
||||||
|
Suite: stable
|
||||||
|
Version: 7.3
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to show: mirror with name mirror-xx not found
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
|
||||||
|
Building download queue...
|
||||||
|
Download queue: 94 items, 0.13 GiB size
|
||||||
|
Downloading & parsing package files...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/dists/hardy/Release...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/dists/hardy/main/binary-amd64/Packages.bz2...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/dists/hardy/main/binary-amd64/Packages.gz...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/dists/hardy/main/binary-i386/Packages.bz2...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/dists/hardy/main/binary-i386/Packages.gz...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-driver/alsa-base_1.0.17.dfsg-2ubuntu1~hardy2_all.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-driver/alsa-source_1.0.17.dfsg-2ubuntu1~hardy2_all.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-driver/linux-sound-base_1.0.17.dfsg-2ubuntu1~hardy2_all.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/lib32asound2-dev_1.0.17a-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/lib32asound2_1.0.17a-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/lib64asound2-dev_1.0.17a-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/lib64asound2_1.0.17a-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/libasound2-dev_1.0.17a-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/libasound2-dev_1.0.17a-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/libasound2-doc_1.0.17a-0ubuntu2~hardy1_all.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/libasound2_1.0.17a-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-lib/libasound2_1.0.17a-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-firmware-loaders_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-firmware-loaders_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-tools-gui_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-tools-gui_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-tools_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/alsa-tools_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/ld10k1_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/ld10k1_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/liblo10k1-0_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/liblo10k1-0_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/liblo10k1-dev_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/liblo10k1-dev_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/qlo10k1_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-tools/qlo10k1_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-utils/alsa-utils_1.0.17-0ubuntu2~hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/a/alsa-utils/alsa-utils_1.0.17-0ubuntu2~hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-386_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-generic_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-generic_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-openvz_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-openvz_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-rt_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-rt_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-server_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-server_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-virtual_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-xen_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-19-xen_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-386_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-generic_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-generic_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-openvz_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-openvz_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-rt_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-rt_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-server_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-server_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-virtual_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-xen_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-headers-lum-2.6.24-21-xen_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-386_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-generic_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-generic_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-openvz_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-openvz_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-rt_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-rt_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-server_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-server_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-virtual_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-xen_2.6.24-19.28+hyper1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-19-xen_2.6.24-19.28+hyper1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-386_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-generic_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-generic_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-openvz_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-openvz_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-rt_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-rt_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-server_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-server_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-virtual_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-xen_2.6.24-21.32+hardy1_amd64.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/linux-ubuntu-modules-2.6.24-21-xen_2.6.24-21.32+hardy1_i386.deb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-19-386-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-19-generic-di_2.6.24-19.28+hyper1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-19-generic-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-21-386-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-21-generic-di_2.6.24-21.32+hardy1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/nic-firmware-2.6.24-21-generic-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-19-386-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-19-generic-di_2.6.24-19.28+hyper1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-19-generic-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-21-386-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-21-generic-di_2.6.24-21.32+hardy1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/scsi-firmware-2.6.24-21-generic-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-19-386-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-19-generic-di_2.6.24-19.28+hyper1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-19-generic-di_2.6.24-19.28+hyper1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-21-386-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-21-generic-di_2.6.24-21.32+hardy1_amd64.udeb...
|
||||||
|
Downloading http://ppa.launchpad.net/alsa-backports/ubuntu/pool/main/l/linux-ubuntu-modules-2.6.24/ubuntu-modules-2.6.24-21-generic-di_2.6.24-21.32+hardy1_i386.udeb...
|
||||||
|
Mirror `alsa-ppa` has been successfully updated.
|
||||||
|
Saving packages to database...
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to update: mirror with name mirror-xyz not found
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"""
|
||||||
|
Testing mirror management
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .create import *
|
||||||
|
from .show import *
|
||||||
|
from .list import *
|
||||||
|
from .update import *
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror1Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: all architectures + all components
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror create mirror1 http://mirror.yandex.ru/debian/ wheezy"
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
self.check_output()
|
||||||
|
self.check_cmd_output("aptly mirror show mirror1", "mirror_show")
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror2Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: all architectures and 1 component
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror create mirror2 http://mirror.yandex.ru/debian/ wheezy main"
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
self.check_output()
|
||||||
|
self.check_cmd_output("aptly mirror show mirror2", "mirror_show")
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror3Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: some architectures and 2 components
|
||||||
|
"""
|
||||||
|
runCmd = "aptly -architectures=i386,amd64 mirror create mirror3 http://mirror.yandex.ru/debian/ wheezy main contrib"
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
self.check_output()
|
||||||
|
self.check_cmd_output("aptly mirror show mirror3", "mirror_show")
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror4Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: missing component
|
||||||
|
"""
|
||||||
|
expectedCode = 1
|
||||||
|
|
||||||
|
runCmd = "aptly -architectures=i386,amd64 mirror create mirror4 http://mirror.yandex.ru/debian/ wheezy life"
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror5Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: missing architecture
|
||||||
|
"""
|
||||||
|
expectedCode = 1
|
||||||
|
|
||||||
|
runCmd = "aptly -architectures=i386,nano68 mirror create mirror5 http://mirror.yandex.ru/debian/ wheezy"
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror6Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: missing release
|
||||||
|
"""
|
||||||
|
expectedCode = 1
|
||||||
|
|
||||||
|
runCmd = "aptly mirror create mirror6 http://mirror.yandex.ru/debian/ suslik"
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror7Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: architectures fixed via config file
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror create mirror7 http://mirror.yandex.ru/debian/ wheezy main contrib"
|
||||||
|
configOverride = {"architectures": ["i386", "amd64"]}
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
self.check_output()
|
||||||
|
self.check_cmd_output("aptly mirror show mirror7", "mirror_show")
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMirror8Test(BaseTest):
|
||||||
|
"""
|
||||||
|
create mirror: already exists
|
||||||
|
"""
|
||||||
|
fixtureCmds = [
|
||||||
|
"aptly mirror create mirror8 http://mirror.yandex.ru/debian/ wheezy main contrib"
|
||||||
|
]
|
||||||
|
runCmd = "aptly mirror create mirror8 http://mirror.yandex.ru/debian/ wheezy main contrib"
|
||||||
|
expectedCode = 1
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class ListMirror1Test(BaseTest):
|
||||||
|
"""
|
||||||
|
list mirrors: regular list
|
||||||
|
"""
|
||||||
|
fixtureCmds = [
|
||||||
|
"aptly mirror create mirror1 http://mirror.yandex.ru/debian/ wheezy",
|
||||||
|
"aptly mirror create mirror2 http://mirror.yandex.ru/debian/ squeeze contrib",
|
||||||
|
"aptly -architectures=i386 mirror create mirror3 http://mirror.yandex.ru/debian/ squeeze non-free",
|
||||||
|
]
|
||||||
|
runCmd = "aptly mirror list"
|
||||||
|
|
||||||
|
|
||||||
|
class ListMirror2Test(BaseTest):
|
||||||
|
"""
|
||||||
|
list mirrors: empty list
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror list"
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMirror1Test(BaseTest):
|
||||||
|
"""
|
||||||
|
show mirror: regular mirror
|
||||||
|
"""
|
||||||
|
fixtureCmds = ["aptly mirror create mirror1 http://mirror.yandex.ru/debian/ wheezy"]
|
||||||
|
runCmd = "aptly mirror show mirror1"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMirror2Test(BaseTest):
|
||||||
|
"""
|
||||||
|
show mirror: missing mirror
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror show mirror-xx"
|
||||||
|
expectedCode = 1
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from lib import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateMirror1Test(BaseTest):
|
||||||
|
"""
|
||||||
|
update mirrors: regular update
|
||||||
|
"""
|
||||||
|
longTest = True
|
||||||
|
fixtureCmds = [
|
||||||
|
"aptly -architectures=i386,amd64 mirror create alsa-ppa http://ppa.launchpad.net/alsa-backports/ubuntu/ hardy main",
|
||||||
|
]
|
||||||
|
runCmd = "aptly mirror update alsa-ppa"
|
||||||
|
|
||||||
|
def output_processor(self, output):
|
||||||
|
return "\n".join(sorted(output.split("\n")))
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateMirror2Test(BaseTest):
|
||||||
|
"""
|
||||||
|
update mirrors: no such repo
|
||||||
|
"""
|
||||||
|
runCmd = "aptly mirror update mirror-xyz"
|
||||||
|
expectedCode = 1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
Snapshot snap1 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap1' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to create snapshot: mirror with name no-such-mirror not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to add snapshot: snapshot with name snap1 already exists
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Arch | Package | Version in A | Version in B
|
||||||
|
[0;32;49m+[0;39;49m all | init-system-helpers | - | 1.11~bpo70.1
|
||||||
|
[0m[0;33;49m![0;39;49m amd64 | libestr0 | 0.1.1-2 | 0.1.9-1~bpo70+1
|
||||||
|
[0m[0;33;49m![0;39;49m amd64 | rsyslog | 5.8.11-3 | 7.4.4-1~bpo70+1
|
||||||
|
[0m[0;33;49m![0;39;49m i386 | libestr0 | 0.1.1-2 | 0.1.9-1~bpo70+1
|
||||||
|
[0m[0;33;49m![0;39;49m i386 | rsyslog | 5.8.11-3 | 7.4.4-1~bpo70+1
|
||||||
|
[0m
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to load snapshot B: snapshot with name snap-no not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to load snapshot A: snapshot with name snap-no not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Snapshots are identical.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
List of snapshots:
|
||||||
|
* [snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
* [snap2]: Snapshot from mirror [wheezy-contrib]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
* [snap3]: Merged from sources: 'snap1', 'snap2'
|
||||||
|
* [snap4]: Pulled into 'snap1' with 'snap2' as source, pull request was: 'mame unrar'
|
||||||
|
|
||||||
|
To get more information about snapshot, run `aptly snapshot show <name>`.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
No snapshots found, create one with `aptly snapshot create...`.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
Snapshot snap3 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap3' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
Snapshot snap2 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap2' to publish snapshot as Debian repository.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Snapshots are identical.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
Snapshot snap4 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap4' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to load snapshot: snapshot with name snap2 not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to create snapshot: snapshot with name snap1 already exists
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
and result would be saved as new snapshot snap3.
|
||||||
|
Loading packages (56830)...
|
||||||
|
Building indexes...
|
||||||
|
[0;32;49m[+][0;39;49m mame-0.146-5_amd64 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m unrar-1:4.1.4-1_amd64 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m mame-0.146-5_i386 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m unrar-1:4.1.4-1_i386 added[0m
|
||||||
|
|
||||||
|
Snapshot snap3 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap3' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-backports]: http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
and result would be saved as new snapshot snap3.
|
||||||
|
Loading packages (58973)...
|
||||||
|
Building indexes...
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m init-system-helpers-1.11~bpo70.1_all added[0m
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_i386 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_i386 added[0m
|
||||||
|
|
||||||
|
Snapshot snap3 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap3' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-backports]: http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
and result would be saved as new snapshot snap3.
|
||||||
|
Loading packages (58973)...
|
||||||
|
Building indexes...
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_i386 added[0m
|
||||||
|
|
||||||
|
Snapshot snap3 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap3' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-backports]: http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
and result would be saved as new snapshot snap3.
|
||||||
|
Loading packages (58973)...
|
||||||
|
Building indexes...
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m init-system-helpers-1.11~bpo70.1_all added[0m
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_i386 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_i386 added[0m
|
||||||
|
|
||||||
|
Not creating snapshot, as dry run was requested.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
List of snapshots:
|
||||||
|
* [snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
* [snap2]: Snapshot from mirror [wheezy-backports]: http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
|
||||||
|
To get more information about snapshot, run `aptly snapshot show <name>`.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to pull: snapshot with name snap-no not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to pull: snapshot with name snap-no not found
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-backports]: http://mirror.yandex.ru/debian/ wheezy-backports
|
||||||
|
and result would be saved as new snapshot snap1.
|
||||||
|
Loading packages (58973)...
|
||||||
|
Building indexes...
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_amd64 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_amd64 added[0m
|
||||||
|
[0;32;49m[+][0;39;49m init-system-helpers-1.11~bpo70.1_all added[0m
|
||||||
|
[0;31;49m[-][0;39;49m rsyslog-5.8.11-3_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m rsyslog-7.4.4-1~bpo70+1_i386 added[0m
|
||||||
|
[0;31;49m[-][0;39;49m libestr0-0.1.1-2_i386 removed[0m
|
||||||
|
[0;32;49m[+][0;39;49m libestr0-0.1.9-1~bpo70+1_i386 added[0m
|
||||||
|
ERROR: unable to create snapshot: snapshot with name snap1 already exists
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Dependencies would be pulled into snapshot:
|
||||||
|
[snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
from snapshot:
|
||||||
|
[snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
and result would be saved as new snapshot snap3.
|
||||||
|
Loading packages (56830)...
|
||||||
|
Building indexes...
|
||||||
|
[0;33;49m[!][0;39;49m [1;39;49mDependency lunar-landing [amd64] can't be satisfied with source [snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy[0;39;49m[0m
|
||||||
|
[0;33;49m[!][0;39;49m [1;39;49mDependency mars-landing (>= 1.0) [amd64] can't be satisfied with source [snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy[0;39;49m[0m
|
||||||
|
[0;33;49m[!][0;39;49m [1;39;49mDependency lunar-landing [i386] can't be satisfied with source [snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy[0;39;49m[0m
|
||||||
|
[0;33;49m[!][0;39;49m [1;39;49mDependency mars-landing (>= 1.0) [i386] can't be satisfied with source [snap2]: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy[0;39;49m[0m
|
||||||
|
|
||||||
|
Snapshot snap3 successfully created.
|
||||||
|
You can run 'aptly publish snapshot snap3' to publish snapshot as Debian repository.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,666 @@
|
|||||||
|
Name: snap1
|
||||||
|
Created At: 2014-01-24 13:06:43 MSK
|
||||||
|
Description: Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy
|
||||||
|
Number of packages: 661
|
||||||
|
Packages:
|
||||||
|
abs-guide-6.5-1_all
|
||||||
|
album-4.06-2_all
|
||||||
|
album-data-4.05-2_all
|
||||||
|
alien-arena-data-7.53-1_all
|
||||||
|
amoeba-data-1.1-6_all
|
||||||
|
assaultcube-data-1.1.0.4+repack1-2.1~deb7u1_all
|
||||||
|
asterisk-prompt-es-1.4-1_all
|
||||||
|
atmel-firmware-1.3-4_all
|
||||||
|
autodocktools-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
automake1.9-doc-1.9.6-1_all
|
||||||
|
bison-doc-1:2.5-1_all
|
||||||
|
bluez-firmware-1.2-3_all
|
||||||
|
broadcom-sta-common-5.100.82.112-8_all
|
||||||
|
broadcom-sta-dkms-5.100.82.112-8_all
|
||||||
|
broadcom-sta-source-5.100.82.112-8_all
|
||||||
|
cclib-data-1.0.1-3_all
|
||||||
|
celestia-common-nonfree-1.6.1-1_all
|
||||||
|
context-doc-nonfree-2012.06.27-2_all
|
||||||
|
context-nonfree-2007.03.22-1_all
|
||||||
|
coq-doc-8.3pl4-1_all
|
||||||
|
coq-doc-html-8.3pl4-1_all
|
||||||
|
coq-doc-pdf-8.3pl4-1_all
|
||||||
|
cpp-4.4-doc-4.4.7-3_all
|
||||||
|
cpp-4.6-doc-4.6.3-2_all
|
||||||
|
cpp-4.7-doc-4.7.2-2_all
|
||||||
|
crash-whitepaper-1.0-1.1_all
|
||||||
|
cuneiform-common-1.1.0+dfsg-4_all
|
||||||
|
dahdi-firmware-nonfree-2.6.1-1_all
|
||||||
|
doc-rfc-20120225-2_all
|
||||||
|
doc-rfc-experimental-20120225-2_all
|
||||||
|
doc-rfc-fyi-bcp-20120225-2_all
|
||||||
|
doc-rfc-informational-20120225-2_all
|
||||||
|
doc-rfc-misc-20120225-2_all
|
||||||
|
doc-rfc-old-std-20120225-2_all
|
||||||
|
doc-rfc-others-20120225-2_all
|
||||||
|
doc-rfc-std-20120225-2_all
|
||||||
|
doc-rfc-std-proposed-20120225-2_all
|
||||||
|
doom-wad-shareware-1.9.fixed-2_all
|
||||||
|
eagle-data-5.12.0-3_all
|
||||||
|
ebook-dev-alp-200407-1_all
|
||||||
|
elmer-doc-2011.09.06-1_all
|
||||||
|
emacs23-common-non-dfsg-23.4+1-1_all
|
||||||
|
emacs24-common-non-dfsg-24.1+1-1_all
|
||||||
|
etoys-4.0.2340-1_all
|
||||||
|
etoys-doc-4.0.2340-1_all
|
||||||
|
festlex-oald-1.4.0-3.1_all
|
||||||
|
festvox-ellpc11k-1.4.0-3_all
|
||||||
|
firmware-atheros-0.36+wheezy.1_all
|
||||||
|
firmware-bnx2-0.36+wheezy.1_all
|
||||||
|
firmware-bnx2x-0.36+wheezy.1_all
|
||||||
|
firmware-brcm80211-0.36+wheezy.1_all
|
||||||
|
firmware-intelwimax-0.36+wheezy.1_all
|
||||||
|
firmware-ipw2x00-0.36+wheezy.1_all
|
||||||
|
firmware-ivtv-0.36+wheezy.1_all
|
||||||
|
firmware-iwlwifi-0.36+wheezy.1_all
|
||||||
|
firmware-libertas-0.36+wheezy.1_all
|
||||||
|
firmware-linux-0.36+wheezy.1_all
|
||||||
|
firmware-linux-nonfree-0.36+wheezy.1_all
|
||||||
|
firmware-myricom-0.36+wheezy.1_all
|
||||||
|
firmware-netxen-0.36+wheezy.1_all
|
||||||
|
firmware-qlogic-0.36+wheezy.1_all
|
||||||
|
firmware-ralink-0.36+wheezy.1_all
|
||||||
|
firmware-realtek-0.36+wheezy.1_all
|
||||||
|
foiltex-2.1.4b-3_all
|
||||||
|
fonts-ipafont-nonfree-jisx0208-00103-19_all
|
||||||
|
fonts-ipafont-nonfree-uigothic-00203-21_all
|
||||||
|
fonts-larabie-deco-1:20011216-4_all
|
||||||
|
fonts-larabie-straight-1:20011216-4_all
|
||||||
|
fonts-larabie-uncommon-1:20011216-4_all
|
||||||
|
fonts-mikachan-9.1-8_all
|
||||||
|
fonts-moe-standard-kai-20120530-1_all
|
||||||
|
fonts-moe-standard-song-20120530-1_all
|
||||||
|
frogatto-data-1.2+dfsg-1_all
|
||||||
|
fsl-4.1.9-7_all
|
||||||
|
fsl-doc-4.1-4.1.9-7_all
|
||||||
|
gawk-doc-4.0.1+ds-1_all
|
||||||
|
gcc-4.4-doc-4.4.7-3_all
|
||||||
|
gcc-4.6-doc-4.6.3-2_all
|
||||||
|
gcc-4.7-doc-4.7.2-2_all
|
||||||
|
gcc-doc-base-4.7.2-2_all
|
||||||
|
gccgo-4.6-doc-4.6.3-2_all
|
||||||
|
gccgo-4.7-doc-4.7.2-2_all
|
||||||
|
gcj-4.6-doc-4.6.3-2_all
|
||||||
|
gcj-4.7-doc-4.7.2-2_all
|
||||||
|
gdb-doc-7.4.1-2_all
|
||||||
|
gfortran-4.4-doc-4.4.7-3_all
|
||||||
|
gfortran-4.6-doc-4.6.3-2_all
|
||||||
|
gfortran-4.7-doc-4.7.2-2_all
|
||||||
|
glibc-doc-reference-2.13-1_all
|
||||||
|
gliese-3.0.95-2_all
|
||||||
|
gmp-doc-5.0.5-1_all
|
||||||
|
gnat-4.4-doc-4.4.7-3_all
|
||||||
|
gnat-4.6-doc-4.6.3-2_all
|
||||||
|
gsfonts-other-6.0-4_all
|
||||||
|
gsl-doc-info-1.15-1_all
|
||||||
|
gsl-doc-pdf-1.15-1_all
|
||||||
|
gsl-ref-html-1.15-1_all
|
||||||
|
gsl-ref-psdoc-1.15-1_all
|
||||||
|
guile-1.8-doc-non-dfsg-1.8.8+1-1.1_all
|
||||||
|
hevea-doc-1.10-3_all
|
||||||
|
hijra-applet-0.2.1-1_all
|
||||||
|
human-icon-theme-0.28.debian-3.3_all
|
||||||
|
hwb-1:040412-3_all
|
||||||
|
icc-profiles-2.0.1-1_all
|
||||||
|
igv-2.0.30-1_all
|
||||||
|
jhove-1.6+dfsg-1_all
|
||||||
|
kstars-data-extra-tycho2-1.1r1-9_all
|
||||||
|
libcolt-java-1.2.0~nojar-2_all
|
||||||
|
libcolt-java-doc-1.2.0~nojar-2_all
|
||||||
|
libcore++-demo-1.7-12_all
|
||||||
|
libcore++-doc-1.7-12_all
|
||||||
|
libcupti-doc-4.2.9-2_all
|
||||||
|
libcwd-doc-1.0.4-1_all
|
||||||
|
libertas-firmware-9.70.7.p0.0-2_all
|
||||||
|
libf2j-java-0.8.1-2_all
|
||||||
|
libgeotiff-epsg-1.3.0-1_all
|
||||||
|
libjabsorb-java-1.3-2_all
|
||||||
|
libjai-core-java-doc-1.1.4-3_all
|
||||||
|
libjai-imageio-core-java-doc-1.2-3_all
|
||||||
|
libmail-sender-perl-0.8.16-2_all
|
||||||
|
libstar-parser-perl-0.59-3_all
|
||||||
|
libttspico-data-1.0+git20110131-2_all
|
||||||
|
libvideo-info-perl-0.993-2_all
|
||||||
|
libworldwind-java-0.5.0-10_all
|
||||||
|
lugaru-data-0~20110520.1+hge4354-1_all
|
||||||
|
make-doc-3.81-5.1_all
|
||||||
|
manpages-posix-2.16-1_all
|
||||||
|
manpages-posix-dev-2.16-1_all
|
||||||
|
mbrola-af1-0.0.20040426-2_all
|
||||||
|
mbrola-br1-2.021-1_all
|
||||||
|
mbrola-br3-2.021-2_all
|
||||||
|
mbrola-cr1-0.0.19981028-2_all
|
||||||
|
mbrola-cz2-0.2-2_all
|
||||||
|
mbrola-de4-0.0.20020812-1_all
|
||||||
|
mbrola-de5-1.0-1_all
|
||||||
|
mbrola-de6-0.0.20021125-2_all
|
||||||
|
mbrola-de7-0.0.20030404-2_all
|
||||||
|
mbrola-ee1-0.0.20020407-1_all
|
||||||
|
mbrola-en1-19980910-2_all
|
||||||
|
mbrola-es1-0.0.19980610-2_all
|
||||||
|
mbrola-es2-2.069-1_all
|
||||||
|
mbrola-fr1-2.050-1_all
|
||||||
|
mbrola-fr4-0.0.19990521-2_all
|
||||||
|
mbrola-gr1-19990610-1_all
|
||||||
|
mbrola-gr2-0.0.20010521-2_all
|
||||||
|
mbrola-hu1-1.002-2_all
|
||||||
|
mbrola-id1-1-2_all
|
||||||
|
mbrola-it3-0.1-2_all
|
||||||
|
mbrola-it4-0.1-2_all
|
||||||
|
mbrola-la1-0.0.20050615-2_all
|
||||||
|
mbrola-mx2-0.1-1_all
|
||||||
|
mbrola-nl2-0.5-2_all
|
||||||
|
mbrola-pl1-0.1-2_all
|
||||||
|
mbrola-pt1-1.0-2_all
|
||||||
|
mbrola-ro1-1.00-2_all
|
||||||
|
mbrola-sw1-1.00-2_all
|
||||||
|
mbrola-sw2-1.0-2_all
|
||||||
|
mbrola-us1-0.3-2_all
|
||||||
|
mbrola-us2-0.1-2_all
|
||||||
|
mbrola-us3-0.1-1_all
|
||||||
|
mbrola-vz1-2-1_all
|
||||||
|
mess-data-0.146-4_all
|
||||||
|
mgltools-cadd-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-dejavu-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-mglutil-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-molkit-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-networkeditor-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-pmv-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-pmv-test-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-pyautodock-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-pybabel-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-scenario2-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-support-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-symserv-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-viewerframework-1.5.6~rc3~cvs.20120206-2_all
|
||||||
|
mgltools-vision-1.5.6~rc3~cvs.20120601-1_all
|
||||||
|
mgltools-visionlibraries-1.5.6~rc3~cvs.20120601-1_all
|
||||||
|
mgltools-volume-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
mgltools-webservices-1.5.6~rc3~cvs.20120206-1_all
|
||||||
|
midisport-firmware-1.2-4_all
|
||||||
|
mpi-specs-20040719-2_all
|
||||||
|
ngspice-doc-24-1_all
|
||||||
|
nikto-1:2.1.4-2_all
|
||||||
|
noshell-4.0.11+notdfsg1-5_all
|
||||||
|
notion-dev-3+2012042300-1_all
|
||||||
|
nvidia-cg-doc-3.1.0013-1_all
|
||||||
|
nvidia-cuda-doc-4.2.9-2_all
|
||||||
|
ocaml-book-en-1.0-5_all
|
||||||
|
ocaml-book-fr-1.0-5_all
|
||||||
|
ocaml-doc-3.12-2_all
|
||||||
|
ooohg-09.12a-8_all
|
||||||
|
openttd-opensfx-0.2.3-3_all
|
||||||
|
os8-2.1-4_all
|
||||||
|
othman-0.2.7-1_all
|
||||||
|
out-of-order-1.0-2_all
|
||||||
|
paml-doc-4.5-1_all
|
||||||
|
parmetis-doc-3.1.1-4_all
|
||||||
|
phy-spread-1.0.3-1_all
|
||||||
|
phylip-doc-1:3.69-1_all
|
||||||
|
picon-domains-2012.05.09-1_all
|
||||||
|
picon-misc-2010.01.02-1_all
|
||||||
|
picon-news-2010.01.02-1_all
|
||||||
|
picon-unknown-2010.01.02-1_all
|
||||||
|
picon-usenix-1995.04.13-8_all
|
||||||
|
picon-users-2012.05.14-1_all
|
||||||
|
picon-weather-2010.01.02-1_all
|
||||||
|
ptex-jtex-1.7+1-13_all
|
||||||
|
python-hijra-0.2.1-1_all
|
||||||
|
python-okasha-0.2.4-1_all
|
||||||
|
python-okasha-examples-0.2.4-1_all
|
||||||
|
python-othman-0.2.7-1_all
|
||||||
|
redeclipse-data-1.2-1_all
|
||||||
|
rubybook-0.2.1-1_all
|
||||||
|
sauerbraten-data-0.0.20100728+repack-1_all
|
||||||
|
scribus-doc-1.4.0+r17300-1_all
|
||||||
|
scribus-ng-doc-1.4.0+r17300-1_all
|
||||||
|
selfhtml-8.1.2-1_all
|
||||||
|
sgb-doc-1:20090810-1_all
|
||||||
|
shapetools-tutorial-1.3-3.1_all
|
||||||
|
sisu-markup-samples-3.0.1-1_all
|
||||||
|
sl-modem-source-2.9.11~20110321-8+deb7u1_all
|
||||||
|
snmp-mibs-downloader-1.1_all
|
||||||
|
spectrum-roms-20081224-3_all
|
||||||
|
spellcast-doc-1.5_all
|
||||||
|
stardict-english-czech-20120601-1_all
|
||||||
|
stardict-german-czech-20120201-1_all
|
||||||
|
t1-xfree86-nonfree-4.2.1-3.1_all
|
||||||
|
tads3-common-1:0.13-2_all
|
||||||
|
tangerine-icon-theme-0.26.debian-3_all
|
||||||
|
tar-doc-1.26-2_all
|
||||||
|
texinfo-doc-nonfree-4.13a-1_all
|
||||||
|
thawab-3.0.13-1_all
|
||||||
|
ttf-ipafont-jisx0208-00103-19_all
|
||||||
|
ttf-ipafont-uigothic-00203-21_all
|
||||||
|
ttf-kochi-gothic-naga10-20030809-14_all
|
||||||
|
ttf-kochi-mincho-naga10-20030809-14_all
|
||||||
|
ttf-larabie-deco-1:20011216-4_all
|
||||||
|
ttf-larabie-straight-1:20011216-4_all
|
||||||
|
ttf-larabie-uncommon-1:20011216-4_all
|
||||||
|
ttf-mikachan-9.1-8_all
|
||||||
|
ttf-xfree86-nonfree-4.2.1-3.1_all
|
||||||
|
ttf-xfree86-nonfree-syriac-4.2.1-3.1_all
|
||||||
|
ttytter-2.1.0-1~deb7u1_all
|
||||||
|
uqm-content-0.6.0+deb1-6_all
|
||||||
|
uqm-music-0.6.0+deb1-6_all
|
||||||
|
uqm-voice-0.6.0+deb1-6_all
|
||||||
|
virtualbox-guest-additions-4.1.18-1_all
|
||||||
|
virtualbox-guest-additions-iso-4.1.18-1_all
|
||||||
|
vmtk-1.0.1-1_all
|
||||||
|
w3-recs-20110107-1_all
|
||||||
|
worldwind-0.5.0-10_all
|
||||||
|
worldwind-doc-0.5.0-10_all
|
||||||
|
xfonts-naga10-1.1-13.1_all
|
||||||
|
xfonts-x3270-misc-3.3.10ga4-2_all
|
||||||
|
xmame-sdl-0.146-5_all
|
||||||
|
xmame-tools-0.146-4_all
|
||||||
|
xmame-x-0.146-5_all
|
||||||
|
xmess-sdl-0.146-4_all
|
||||||
|
xmess-x-0.146-4_all
|
||||||
|
xml2rfc-1.36-5_all
|
||||||
|
xtide-data-nonfree-20100529-1_all
|
||||||
|
yale-5.0.95-2_all
|
||||||
|
zangband-data-1:2.7.5pre1-8_all
|
||||||
|
zd1211-firmware-2.21.0.0-1_all
|
||||||
|
zekr-1.0.0+repack-7_all
|
||||||
|
zeroc-ice-manual-3.4.2-1_all
|
||||||
|
3270-common-3.3.10ga4-2+b1_amd64
|
||||||
|
abyss-1.3.4-3_amd64
|
||||||
|
agrep-4.17-9_amd64
|
||||||
|
amd-clinfo-1:12-6+point-3_amd64
|
||||||
|
amd-libopencl1-1:12-6+point-3_amd64
|
||||||
|
amd-opencl-dev-1:12-6+point-3_amd64
|
||||||
|
amd-opencl-icd-1:12-6+point-3_amd64
|
||||||
|
amd64-microcode-1.20120910-2_amd64
|
||||||
|
amiwm-0.20.48-8_amd64
|
||||||
|
blimps-examples-3.9-1_amd64
|
||||||
|
blimps-utils-3.9-1_amd64
|
||||||
|
bsdgames-nonfree-2.17-5_amd64
|
||||||
|
bugsx-1.08-12_amd64
|
||||||
|
c3270-3.3.10ga4-2+b1_amd64
|
||||||
|
clustalw-mpi-0.15-2_amd64
|
||||||
|
conserver-client-8.1.18-2.2_amd64
|
||||||
|
conserver-server-8.1.18-2.2_amd64
|
||||||
|
crafty-23.4-6_amd64
|
||||||
|
cufflinks-1.3.0-2_amd64
|
||||||
|
cuneiform-1.1.0+dfsg-4_amd64
|
||||||
|
dynamips-0.2.7-0.2.8RC2-5.1_amd64
|
||||||
|
embassy-phylip-3.69+20110714-1_amd64
|
||||||
|
f2j-0.8.1-2_amd64
|
||||||
|
fatrat-unpack-1.1.3-2_amd64
|
||||||
|
fglrx-atieventsd-1:12-6+point-3_amd64
|
||||||
|
fglrx-control-1:12-6+point-3_amd64
|
||||||
|
fglrx-driver-1:12-6+point-3_amd64
|
||||||
|
fglrx-glx-1:12-6+point-3_amd64
|
||||||
|
fglrx-glx-ia32-1:12-6+point-3_amd64
|
||||||
|
fglrx-modules-dkms-1:12-6+point-3_amd64
|
||||||
|
fglrx-source-1:12-6+point-3_amd64
|
||||||
|
frobtads-1:0.13-2_amd64
|
||||||
|
fsl-4.1-4.1.9-7_amd64
|
||||||
|
gmap-2012-06-12-1_amd64
|
||||||
|
intel-microcode-1.20130906.1_amd64
|
||||||
|
iozone3-397-2_amd64
|
||||||
|
kic-2.4a-1.1_amd64
|
||||||
|
libapache2-mod-fastcgi-2.4.7~0910052141-1_amd64
|
||||||
|
libblimps3-3.9-1_amd64
|
||||||
|
libblimps3-dev-3.9-1_amd64
|
||||||
|
libcamlpdf-ocaml-dev-0.5-1+b2_amd64
|
||||||
|
libcg-3.1.0013-1_amd64
|
||||||
|
libcggl-3.1.0013-1_amd64
|
||||||
|
libclamunrar6-0.96.4-1_amd64
|
||||||
|
libcore++-dev-1.7-12_amd64
|
||||||
|
libcore++1c2-1.7-12_amd64
|
||||||
|
libcublas4-4.2.9-2_amd64
|
||||||
|
libcuda1-304.88-1+deb7u1_amd64
|
||||||
|
libcuda1-ia32-304.88-1+deb7u1_amd64
|
||||||
|
libcudart4-4.2.9-2_amd64
|
||||||
|
libcufft4-4.2.9-2_amd64
|
||||||
|
libcuinj4-4.2.9-2_amd64
|
||||||
|
libcuneiform-dev-1.1.0+dfsg-4_amd64
|
||||||
|
libcuneiform0-1.1.0+dfsg-4_amd64
|
||||||
|
libcupti-dev-4.2.9-2_amd64
|
||||||
|
libcupti4-4.2.9-2_amd64
|
||||||
|
libcurand4-4.2.9-2_amd64
|
||||||
|
libcusparse4-4.2.9-2_amd64
|
||||||
|
libcwd-1.0.4-1_amd64
|
||||||
|
libfglrx-1:12-6+point-3_amd64
|
||||||
|
libfglrx-amdxvba1-1:12-6+point-3_amd64
|
||||||
|
libfglrx-ia32-1:12-6+point-3_amd64
|
||||||
|
libgl1-fglrx-glx-1:12-6+point-3_amd64
|
||||||
|
libgl1-nvidia-alternatives-304.88-1+deb7u1_amd64
|
||||||
|
libgl1-nvidia-alternatives-ia32-304.88-1+deb7u1_amd64
|
||||||
|
libgl1-nvidia-glx-304.88-1+deb7u1_amd64
|
||||||
|
libgl1-nvidia-glx-ia32-304.88-1+deb7u1_amd64
|
||||||
|
libgl1-nvidia-legacy-173xx-glx-173.14.35-4_amd64
|
||||||
|
libgl1-nvidia-legacy-173xx-glx-ia32-173.14.35-4_amd64
|
||||||
|
libgl1-nvidia-legacy-71xx-glx-71.86.15-3_amd64
|
||||||
|
libgl1-nvidia-legacy-71xx-glx-ia32-71.86.15-3_amd64
|
||||||
|
libgl1-nvidia-legacy-96xx-glx-96.43.23-3_amd64
|
||||||
|
libgl1-nvidia-legacy-96xx-glx-ia32-96.43.23-3_amd64
|
||||||
|
libglx-nvidia-alternatives-304.88-1+deb7u1_amd64
|
||||||
|
libjai-core-java-1.1.4-3_amd64
|
||||||
|
libjai-imageio-core-java-1.2-3_amd64
|
||||||
|
libmath-random-perl-0.71-3+b1_amd64
|
||||||
|
libmetis-edf-dev-4.1-2-3_amd64
|
||||||
|
libmetis-edf4.1-4.1-2-3_amd64
|
||||||
|
libmotif-dev-2.3.3-8_amd64
|
||||||
|
libmotif4-2.3.3-8_amd64
|
||||||
|
libmotif4-dbg-2.3.3-8_amd64
|
||||||
|
libnauty-dev-2.4r2-1_amd64
|
||||||
|
libnauty1d-2.4r2-1_amd64
|
||||||
|
libnpp4-4.2.9-2_amd64
|
||||||
|
libnvcuvid1-304.88-1+deb7u1_amd64
|
||||||
|
libnvidia-compiler-304.88-1+deb7u1_amd64
|
||||||
|
libnvidia-compiler-ia32-304.88-1+deb7u1_amd64
|
||||||
|
libnvidia-ml1-304.88-1+deb7u1_amd64
|
||||||
|
libparmetis-dev-3.1.1-4_amd64
|
||||||
|
libparmetis3.1-3.1.1-4_amd64
|
||||||
|
libtet1.4-1.4.3-1_amd64
|
||||||
|
libtet1.4-dev-1.4.3-1_amd64
|
||||||
|
libtriangle-1.6-1.6-2_amd64
|
||||||
|
libtriangle-dev-1.6-2_amd64
|
||||||
|
libttspico-dev-1.0+git20110131-2_amd64
|
||||||
|
libttspico-utils-1.0+git20110131-2_amd64
|
||||||
|
libttspico0-1.0+git20110131-2_amd64
|
||||||
|
libvmtk-dev-1.0.1-1_amd64
|
||||||
|
libvmtk1.0-1.0.1-1_amd64
|
||||||
|
libxvbaw-dev-1:12-6+point-3_amd64
|
||||||
|
libxvmcnvidia1-304.88-1+deb7u1_amd64
|
||||||
|
madfuload-1.2-4_amd64
|
||||||
|
mame-0.146-5_amd64
|
||||||
|
mame-tools-0.146-4_amd64
|
||||||
|
mbrola-3.01h-6_amd64
|
||||||
|
mess-0.146-4_amd64
|
||||||
|
metis-edf-4.1-2-3_amd64
|
||||||
|
mgltools-bhtree-1.5.6~rc3~cvs.20120206-1_amd64
|
||||||
|
mgltools-geomutils-1.5.6~rc3~cvs.20120601-1_amd64
|
||||||
|
mgltools-gle-1.5.6~rc3~cvs.20120601-1_amd64
|
||||||
|
mgltools-opengltk-1.5.6~rc3~cvs.20120601-2_amd64
|
||||||
|
mgltools-pyglf-1.5.6~rc3~cvs.20120601-1_amd64
|
||||||
|
mgltools-sff-1.5.6~rc3~cvs.20120206-1_amd64
|
||||||
|
mgltools-utpackages-1.5.6~rc3~cvs.20120601-1_amd64
|
||||||
|
motif-clients-2.3.3-8_amd64
|
||||||
|
mssstest-3.0-3_amd64
|
||||||
|
nautilus-dropbox-1.4.0-3_amd64
|
||||||
|
nauty-2.4r2-1_amd64
|
||||||
|
netperf-2.4.4-6.1_amd64
|
||||||
|
ngspice-24-1_amd64
|
||||||
|
notion-3+2012042300-1_amd64
|
||||||
|
nttcp-1.47-13_amd64
|
||||||
|
nvidia-alternative-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-alternative-legacy-173xx-173.14.35-4_amd64
|
||||||
|
nvidia-alternative-legacy-71xx-71.86.15-3_amd64
|
||||||
|
nvidia-alternative-legacy-96xx-96.43.23-3_amd64
|
||||||
|
nvidia-cg-dev-3.1.0013-1_amd64
|
||||||
|
nvidia-cg-toolkit-3.1.0013-1_amd64
|
||||||
|
nvidia-cuda-dev-4.2.9-2_amd64
|
||||||
|
nvidia-cuda-gdb-4.2.9-2_amd64
|
||||||
|
nvidia-cuda-toolkit-4.2.9-2_amd64
|
||||||
|
nvidia-detect-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-glx-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-glx-ia32-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-glx-legacy-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-173xx-173.14.35-4_amd64
|
||||||
|
nvidia-glx-legacy-173xx-ia32-173.14.35-4_amd64
|
||||||
|
nvidia-glx-legacy-71xx-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-71xx-dev-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-71xx-ia32-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-71xx-unsupported-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-96xx-96.43.23-3_amd64
|
||||||
|
nvidia-glx-legacy-96xx-ia32-96.43.23-3_amd64
|
||||||
|
nvidia-glx-legacy-dev-71.86.15-3_amd64
|
||||||
|
nvidia-glx-legacy-ia32-71.86.15-3_amd64
|
||||||
|
nvidia-kernel-2.6-amd64-304.88+1_amd64
|
||||||
|
nvidia-kernel-3.2.0-4-amd64-304.88+1+1+3.2.41-2_amd64
|
||||||
|
nvidia-kernel-amd64-304.88+1_amd64
|
||||||
|
nvidia-kernel-dkms-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-kernel-legacy-173xx-dkms-173.14.35-4_amd64
|
||||||
|
nvidia-kernel-legacy-173xx-source-173.14.35-4_amd64
|
||||||
|
nvidia-kernel-legacy-71xx-dkms-71.86.15-3_amd64
|
||||||
|
nvidia-kernel-legacy-71xx-source-71.86.15-3_amd64
|
||||||
|
nvidia-kernel-legacy-96xx-dkms-96.43.23-3_amd64
|
||||||
|
nvidia-kernel-legacy-96xx-source-96.43.23-3_amd64
|
||||||
|
nvidia-kernel-legacy-source-71.86.15-3_amd64
|
||||||
|
nvidia-kernel-source-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-libopencl1-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-libopencl1-ia32-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-opencl-common-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-opencl-dev-4.2.9-2_amd64
|
||||||
|
nvidia-opencl-icd-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-opencl-icd-ia32-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-smi-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-vdpau-driver-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-vdpau-driver-ia32-304.88-1+deb7u1_amd64
|
||||||
|
nvidia-visual-profiler-4.2.9-2_amd64
|
||||||
|
p7zip-rar-9.20.1~ds.1-3_amd64
|
||||||
|
paml-4.5-1_amd64
|
||||||
|
parmetis-test-3.1.1-4_amd64
|
||||||
|
pgplot5-5.2.2-19_amd64
|
||||||
|
phylip-1:3.69-1_amd64
|
||||||
|
powder-117-1_amd64
|
||||||
|
pptview-8.0-7_amd64
|
||||||
|
pr3287-3.3.10ga4-2+b1_amd64
|
||||||
|
python-vmtk-1.0.1-1_amd64
|
||||||
|
r-cran-maptools-1:0.7-38-1_amd64
|
||||||
|
rar-2:4.0.b3-1_amd64
|
||||||
|
s3270-3.3.10ga4-2+b1_amd64
|
||||||
|
sdlmame-0.146-5_amd64
|
||||||
|
sdlmame-tools-0.146-4_amd64
|
||||||
|
seaview-1:4.3.3-3_amd64
|
||||||
|
seq-gen-1.3.3-1_amd64
|
||||||
|
sgb-1:20090810-1_amd64
|
||||||
|
sift-4.0.3b-3_amd64
|
||||||
|
sl-modem-daemon-2.9.11~20110321-8+deb7u1_amd64
|
||||||
|
sl-modem-dkms-2.9.11~20110321-8+deb7u1_amd64
|
||||||
|
sparse-0.4.3+20110419-1_amd64
|
||||||
|
tads2-dev-1:0.13-2_amd64
|
||||||
|
tads3-dev-1:0.13-2_amd64
|
||||||
|
tclspice-24-1_amd64
|
||||||
|
teamspeak-client-2.0.32-3.1_amd64
|
||||||
|
tetgen-1.4.3-1_amd64
|
||||||
|
titantools-4.0.11+notdfsg1-5_amd64
|
||||||
|
tome-2.3.5-2_amd64
|
||||||
|
triangle-bin-1.6-2_amd64
|
||||||
|
trn4-4.0-test77-6_amd64
|
||||||
|
unace-nonfree-2.5-7_amd64
|
||||||
|
unrar-1:4.1.4-1_amd64
|
||||||
|
wap-wml-tools-0.0.4-6_amd64
|
||||||
|
x3270-3.3.10ga4-2+b1_amd64
|
||||||
|
xfractint-20.4.10-2_amd64
|
||||||
|
xserver-xorg-video-nvidia-304.88-1+deb7u1_amd64
|
||||||
|
xserver-xorg-video-nvidia-legacy-173xx-173.14.35-4_amd64
|
||||||
|
xserver-xorg-video-nvidia-legacy-71xx-71.86.15-3_amd64
|
||||||
|
xserver-xorg-video-nvidia-legacy-96xx-96.43.23-3_amd64
|
||||||
|
xsnow-1:1.42-9_amd64
|
||||||
|
zangband-1:2.7.5pre1-8_amd64
|
||||||
|
3270-common-3.3.10ga4-2+b1_i386
|
||||||
|
amd-clinfo-1:12-6+point-3_i386
|
||||||
|
amd-libopencl1-1:12-6+point-3_i386
|
||||||
|
amd-opencl-dev-1:12-6+point-3_i386
|
||||||
|
amd-opencl-icd-1:12-6+point-3_i386
|
||||||
|
amd64-microcode-1.20120910-2_i386
|
||||||
|
amiwm-0.20.48-8_i386
|
||||||
|
axe-6.1.2-15.1_i386
|
||||||
|
bsdgames-nonfree-2.17-5_i386
|
||||||
|
bugsx-1.08-12_i386
|
||||||
|
c3270-3.3.10ga4-2+b1_i386
|
||||||
|
conserver-client-8.1.18-2.2_i386
|
||||||
|
conserver-server-8.1.18-2.2_i386
|
||||||
|
crafty-23.4-6_i386
|
||||||
|
cuneiform-1.1.0+dfsg-4_i386
|
||||||
|
dgen-1.23-12_i386
|
||||||
|
drdsl-1.2.0-1_i386
|
||||||
|
dynamips-0.2.7-0.2.8RC2-5.1_i386
|
||||||
|
eagle-5.12.0-3_i386
|
||||||
|
f2j-0.8.1-2_i386
|
||||||
|
fatrat-unpack-1.1.3-2_i386
|
||||||
|
fglrx-atieventsd-1:12-6+point-3_i386
|
||||||
|
fglrx-control-1:12-6+point-3_i386
|
||||||
|
fglrx-driver-1:12-6+point-3_i386
|
||||||
|
fglrx-glx-1:12-6+point-3_i386
|
||||||
|
fglrx-modules-dkms-1:12-6+point-3_i386
|
||||||
|
fglrx-source-1:12-6+point-3_i386
|
||||||
|
fsl-4.1-4.1.9-7_i386
|
||||||
|
intel-microcode-1.20130906.1_i386
|
||||||
|
iozone3-397-2_i386
|
||||||
|
irpas-0.10-4.1_i386
|
||||||
|
lgrind-3.67-3_i386
|
||||||
|
libapache2-mod-fastcgi-2.4.7~0910052141-1_i386
|
||||||
|
libcamlpdf-ocaml-dev-0.5-1+b2_i386
|
||||||
|
libcg-3.1.0013-1_i386
|
||||||
|
libcggl-3.1.0013-1_i386
|
||||||
|
libclamunrar6-0.96.4-1_i386
|
||||||
|
libcore++-dev-1.7-12_i386
|
||||||
|
libcore++1c2-1.7-12_i386
|
||||||
|
libcublas4-4.2.9-2_i386
|
||||||
|
libcuda1-304.88-1+deb7u1_i386
|
||||||
|
libcudart4-4.2.9-2_i386
|
||||||
|
libcufft4-4.2.9-2_i386
|
||||||
|
libcuinj4-4.2.9-2_i386
|
||||||
|
libcuneiform-dev-1.1.0+dfsg-4_i386
|
||||||
|
libcuneiform0-1.1.0+dfsg-4_i386
|
||||||
|
libcupti-dev-4.2.9-2_i386
|
||||||
|
libcupti4-4.2.9-2_i386
|
||||||
|
libcurand4-4.2.9-2_i386
|
||||||
|
libcusparse4-4.2.9-2_i386
|
||||||
|
libcwd-1.0.4-1_i386
|
||||||
|
libfglrx-1:12-6+point-3_i386
|
||||||
|
libfglrx-amdxvba1-1:12-6+point-3_i386
|
||||||
|
libgl1-fglrx-glx-1:12-6+point-3_i386
|
||||||
|
libgl1-nvidia-alternatives-304.88-1+deb7u1_i386
|
||||||
|
libgl1-nvidia-glx-304.88-1+deb7u1_i386
|
||||||
|
libgl1-nvidia-legacy-173xx-glx-173.14.35-4_i386
|
||||||
|
libgl1-nvidia-legacy-71xx-glx-71.86.15-3_i386
|
||||||
|
libgl1-nvidia-legacy-96xx-glx-96.43.23-3_i386
|
||||||
|
libglx-nvidia-alternatives-304.88-1+deb7u1_i386
|
||||||
|
libgpcl-dev-2.32-1_i386
|
||||||
|
libgpcl0-2.32-1_i386
|
||||||
|
libmath-random-perl-0.71-3+b1_i386
|
||||||
|
libmotif-dev-2.3.3-8_i386
|
||||||
|
libmotif4-2.3.3-8_i386
|
||||||
|
libmotif4-dbg-2.3.3-8_i386
|
||||||
|
libnauty-dev-2.4r2-1_i386
|
||||||
|
libnauty1d-2.4r2-1_i386
|
||||||
|
libnpp4-4.2.9-2_i386
|
||||||
|
libnvcuvid1-304.88-1+deb7u1_i386
|
||||||
|
libnvidia-compiler-304.88-1+deb7u1_i386
|
||||||
|
libnvidia-ml1-304.88-1+deb7u1_i386
|
||||||
|
libparmetis-dev-3.1.1-4_i386
|
||||||
|
libparmetis3.1-3.1.1-4_i386
|
||||||
|
libtet1.4-1.4.3-1_i386
|
||||||
|
libtet1.4-dev-1.4.3-1_i386
|
||||||
|
libtriangle-1.6-1.6-2_i386
|
||||||
|
libtriangle-dev-1.6-2_i386
|
||||||
|
libttspico-dev-1.0+git20110131-2_i386
|
||||||
|
libttspico-utils-1.0+git20110131-2_i386
|
||||||
|
libttspico0-1.0+git20110131-2_i386
|
||||||
|
libvmtk-dev-1.0.1-1_i386
|
||||||
|
libvmtk1.0-1.0.1-1_i386
|
||||||
|
libxvbaw-dev-1:12-6+point-3_i386
|
||||||
|
libxvmcnvidia1-304.88-1+deb7u1_i386
|
||||||
|
madfuload-1.2-4_i386
|
||||||
|
mame-0.146-5_i386
|
||||||
|
mame-tools-0.146-4_i386
|
||||||
|
martian-modem-20080625-2_i386
|
||||||
|
martian-modem-source-20080625-2_i386
|
||||||
|
mbrola-3.01h-6_i386
|
||||||
|
mess-0.146-4_i386
|
||||||
|
mgltools-bhtree-1.5.6~rc3~cvs.20120206-1_i386
|
||||||
|
mgltools-geomutils-1.5.6~rc3~cvs.20120601-1_i386
|
||||||
|
mgltools-gle-1.5.6~rc3~cvs.20120601-1_i386
|
||||||
|
mgltools-opengltk-1.5.6~rc3~cvs.20120601-2_i386
|
||||||
|
mgltools-pyglf-1.5.6~rc3~cvs.20120601-1_i386
|
||||||
|
mgltools-sff-1.5.6~rc3~cvs.20120206-1_i386
|
||||||
|
mgltools-utpackages-1.5.6~rc3~cvs.20120601-1_i386
|
||||||
|
motif-clients-2.3.3-8_i386
|
||||||
|
mssstest-3.0-3_i386
|
||||||
|
nautilus-dropbox-1.4.0-3_i386
|
||||||
|
nauty-2.4r2-1_i386
|
||||||
|
netperf-2.4.4-6.1_i386
|
||||||
|
notion-3+2012042300-1_i386
|
||||||
|
nvidia-alternative-304.88-1+deb7u1_i386
|
||||||
|
nvidia-alternative-legacy-173xx-173.14.35-4_i386
|
||||||
|
nvidia-alternative-legacy-71xx-71.86.15-3_i386
|
||||||
|
nvidia-alternative-legacy-96xx-96.43.23-3_i386
|
||||||
|
nvidia-cg-dev-3.1.0013-1_i386
|
||||||
|
nvidia-cg-toolkit-3.1.0013-1_i386
|
||||||
|
nvidia-cuda-dev-4.2.9-2_i386
|
||||||
|
nvidia-cuda-gdb-4.2.9-2_i386
|
||||||
|
nvidia-cuda-toolkit-4.2.9-2_i386
|
||||||
|
nvidia-detect-304.88-1+deb7u1_i386
|
||||||
|
nvidia-glx-304.88-1+deb7u1_i386
|
||||||
|
nvidia-glx-legacy-71.86.15-3_i386
|
||||||
|
nvidia-glx-legacy-173xx-173.14.35-4_i386
|
||||||
|
nvidia-glx-legacy-71xx-71.86.15-3_i386
|
||||||
|
nvidia-glx-legacy-71xx-dev-71.86.15-3_i386
|
||||||
|
nvidia-glx-legacy-71xx-unsupported-71.86.15-3_i386
|
||||||
|
nvidia-glx-legacy-96xx-96.43.23-3_i386
|
||||||
|
nvidia-glx-legacy-dev-71.86.15-3_i386
|
||||||
|
nvidia-kernel-2.6-486-304.88+1_i386
|
||||||
|
nvidia-kernel-2.6-686-pae-304.88+1_i386
|
||||||
|
nvidia-kernel-2.6-amd64-304.88+1_i386
|
||||||
|
nvidia-kernel-3.2.0-4-486-304.88+1+1+3.2.41-2_i386
|
||||||
|
nvidia-kernel-3.2.0-4-686-pae-304.88+1+1+3.2.41-2_i386
|
||||||
|
nvidia-kernel-3.2.0-4-amd64-304.88+1+1+3.2.41-2_i386
|
||||||
|
nvidia-kernel-486-304.88+1_i386
|
||||||
|
nvidia-kernel-686-pae-304.88+1_i386
|
||||||
|
nvidia-kernel-amd64-304.88+1_i386
|
||||||
|
nvidia-kernel-dkms-304.88-1+deb7u1_i386
|
||||||
|
nvidia-kernel-legacy-173xx-dkms-173.14.35-4_i386
|
||||||
|
nvidia-kernel-legacy-173xx-source-173.14.35-4_i386
|
||||||
|
nvidia-kernel-legacy-71xx-dkms-71.86.15-3_i386
|
||||||
|
nvidia-kernel-legacy-71xx-source-71.86.15-3_i386
|
||||||
|
nvidia-kernel-legacy-96xx-dkms-96.43.23-3_i386
|
||||||
|
nvidia-kernel-legacy-96xx-source-96.43.23-3_i386
|
||||||
|
nvidia-kernel-legacy-source-71.86.15-3_i386
|
||||||
|
nvidia-kernel-source-304.88-1+deb7u1_i386
|
||||||
|
nvidia-libopencl1-304.88-1+deb7u1_i386
|
||||||
|
nvidia-opencl-common-304.88-1+deb7u1_i386
|
||||||
|
nvidia-opencl-dev-4.2.9-2_i386
|
||||||
|
nvidia-opencl-icd-304.88-1+deb7u1_i386
|
||||||
|
nvidia-smi-304.88-1+deb7u1_i386
|
||||||
|
nvidia-vdpau-driver-304.88-1+deb7u1_i386
|
||||||
|
nvidia-visual-profiler-4.2.9-2_i386
|
||||||
|
p7zip-rar-9.20.1~ds.1-3_i386
|
||||||
|
parmetis-test-3.1.1-4_i386
|
||||||
|
pgplot5-5.2.2-19_i386
|
||||||
|
phylip-1:3.69-1_i386
|
||||||
|
pptview-8.0-7_i386
|
||||||
|
pr3287-3.3.10ga4-2+b1_i386
|
||||||
|
python-vmtk-1.0.1-1_i386
|
||||||
|
r-cran-maptools-1:0.7-38-1_i386
|
||||||
|
rar-2:4.0.b3-1_i386
|
||||||
|
s3270-3.3.10ga4-2+b1_i386
|
||||||
|
sdlmame-0.146-5_i386
|
||||||
|
sdlmame-tools-0.146-4_i386
|
||||||
|
seaview-1:4.3.3-3_i386
|
||||||
|
seq-gen-1.3.3-1_i386
|
||||||
|
sgb-1:20090810-1_i386
|
||||||
|
sl-modem-daemon-2.9.11~20110321-8+deb7u1_i386
|
||||||
|
sl-modem-dkms-2.9.11~20110321-8+deb7u1_i386
|
||||||
|
sparse-0.4.3+20110419-1_i386
|
||||||
|
spellcast-1.0-21_i386
|
||||||
|
teamspeak-client-2.0.32-3.1_i386
|
||||||
|
teamspeak-server-2.0.24.1+debian-1.1_i386
|
||||||
|
tetgen-1.4.3-1_i386
|
||||||
|
titantools-4.0.11+notdfsg1-5_i386
|
||||||
|
tome-2.3.5-2_i386
|
||||||
|
triangle-bin-1.6-2_i386
|
||||||
|
trn-3.6-23_i386
|
||||||
|
trn4-4.0-test77-6_i386
|
||||||
|
unace-nonfree-2.5-7_i386
|
||||||
|
unrar-1:4.1.4-1_i386
|
||||||
|
wap-wml-tools-0.0.4-6_i386
|
||||||
|
x3270-3.3.10ga4-2+b1_i386
|
||||||
|
xfractint-20.4.10-2_i386
|
||||||
|
xmame-svga-0.146-5_i386
|
||||||
|
xserver-xorg-video-nvidia-304.88-1+deb7u1_i386
|
||||||
|
xserver-xorg-video-nvidia-legacy-173xx-173.14.35-4_i386
|
||||||
|
xserver-xorg-video-nvidia-legacy-71xx-71.86.15-3_i386
|
||||||
|
xserver-xorg-video-nvidia-legacy-96xx-96.43.23-3_i386
|
||||||
|
zangband-1:2.7.5pre1-8_i386
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to show: snapshot with name no-such-snapshot not found
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Missing dependencies (11):
|
||||||
|
fenix [amd64]
|
||||||
|
fenix-plugins-system [amd64]
|
||||||
|
ia32-libs-gtk-i386 [amd64]
|
||||||
|
ia32-libs-i386 [amd64]
|
||||||
|
kbdcontrol [amd64]
|
||||||
|
kbdcontrol [i386]
|
||||||
|
mozart (>= 1.4.0) [amd64]
|
||||||
|
scsh-0.6 (>= 0.6.6) [amd64]
|
||||||
|
scsh-0.6 [amd64]
|
||||||
|
vidcontrol [amd64]
|
||||||
|
vidcontrol [i386]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ERROR: unable to verify: snapshot with name no-such-snapshot not found
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Missing dependencies (2):
|
||||||
|
kbdcontrol [i386]
|
||||||
|
vidcontrol [i386]
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user