Compare commits

..

126 Commits

Author SHA1 Message Date
Andrey Smirnov a6541aac41 Fix temporary contents DB being left behind after publishing
NB: Go `defer` order execution is reverse to the order `defer` statements
are executed.

So before the change, `Drop()` was called before `Close()`, which was no-op.

Change that to explicit order in single func, print errors if they happen.
2017-04-11 00:32:21 +03:00
Andrey Smirnov 7fd8bd0171 Merge pull request #531 from smira/release-1.0.0-preparation
Prepare for new release, update build instructions [ci skip]
2017-03-28 00:17:08 +03:00
Andrey Smirnov 4707efe4d6 Prepare for new release, update build instructions [ci skip] 2017-03-28 00:15:41 +03:00
Andrey Smirnov 8ae61f9448 Merge pull request #523 from smira/versioning
Automatic versioning for aptly
2017-03-27 16:02:25 +03:00
Andrey Smirnov a138d0111d Update README to use go install which will build with version 2017-03-26 19:24:32 +03:00
Andrey Smirnov af1adb44ce Remove -x flag for go install 2017-03-26 19:23:53 +03:00
Andrey Smirnov 2943422d5d Automatic versioning for aptly
New version format:

* for releases, `x.y.z` (follows tag without leading `v`)
* for nightly builds, `x.y.z+N+hash` (previous version, not the upcoming one)

This means that each nightly build `aptly` would report
correct version now.

Version is now complied into the aptly binary, system tests
automatically check for current version, no need to update them
anymore.
2017-03-25 00:18:45 +03:00
Andrey Smirnov 91219e3a0a Merge pull request #522 from smira/man-gen-rework
Rework man generator with new `go install` format
2017-03-24 21:50:28 +03:00
Andrey Smirnov 7f8db9087a Rework man generator with new go install format
With previous version, `go install` automatically picks up
package `man` and installs `gen.go` as `main` to the $GOPATH/bin which
is not what is expected. Move man page generator to separate
private folder.
2017-03-24 21:07:38 +03:00
Andrey Smirnov 92c844b8ac Merge pull request #517 from smira/goreportcard
Fix goreportcard badge [ci skip]
2017-03-23 18:33:00 +03:00
Andrey Smirnov 2b56a3937b Fix goreportcard badge [ci skip] 2017-03-23 18:32:00 +03:00
Andrey Smirnov 9cea9b6470 Merge pull request #512 from smira/500-xdg-open
Customize viewer per platform
2017-03-23 18:28:24 +03:00
Andrey Smirnov e3e68b9f22 Customize viewer per platform 2017-03-23 17:12:34 +03:00
Andrey Smirnov d56839664d Merge pull request #513 from smira/gometalinter
Switch to gometalinter
2017-03-23 16:32:33 +03:00
Andrey Smirnov 516dd7b044 Switch to gometalinter
Only small amount of required checks is enabled,
plan is to enable more linters as issues are fixed in the code.
2017-03-23 01:51:08 +03:00
Andrey Smirnov 53e59d3765 Merge pull request #509 from smira/golint-govet
Add govet/golint into Travis CI build
2017-03-22 22:14:30 +03:00
Andrey Smirnov 11d828b3b1 Add govet/golint into Travis CI build
Fix current issues
2017-03-22 21:49:16 +03:00
Andrey Smirnov 07472bec50 Merge pull request #511 from smira/dep-experiment
Convert to regular Go vendor + `dep` tool
2017-03-22 20:34:36 +03:00
Andrey Smirnov f737787c01 Fix up system tests 2017-03-22 19:56:23 +03:00
Andrey Smirnov c6c1012330 Conver to regular Go vendor + dep tool 2017-03-22 19:24:06 +03:00
Andrey Smirnov 070347295e Merge pull request #505 from smira/rmedaer-master
Added '.xz' extension in HTTP download.
2017-03-17 00:47:33 +03:00
Andrey Smirnov acd8d4a6ea Go 1.6 compatibility 2017-03-17 00:17:07 +03:00
Andrey Smirnov c9768416ed Fix up tests 2017-03-16 23:06:41 +03:00
Raphael Medaer bfb9ffad1d Added expected error on 'Packages.xz' for TestDownload[WithSources]Flat. 2017-03-16 22:41:25 +03:00
Raphael Medaer 9cfe1307e3 Added download tests for xz compression. 2017-03-16 22:41:25 +03:00
Raphael Medaer db8595711b Added '.xz' reader in HTTP download. This fixed issue when you try to mirror a distribution with only Packages.xz (example 'debian/experimental'). 2017-03-16 22:41:25 +03:00
Andrey Smirnov ce0001f94c Merge pull request #504 from smira/go-1.8
Add Travis CI build on Go 1.8
2017-03-16 22:16:01 +03:00
Andrey Smirnov b102562478 Fix up system test for Go 1.8 2017-03-16 20:58:21 +03:00
Andrey Smirnov 69cbe10690 Add Travis CI build on Go 1.8 2017-03-16 18:46:03 +03:00
Andrey Smirnov e3e4ea91bd Merge pull request #502 from smira/aws-sdk-bump
Bump Go AWS SDK to the latest version
2017-03-16 18:45:26 +03:00
Andrey Smirnov 02c582e227 Merge pull request #503 from smira/pr-template-update
Add bash completion to PR template [ci skip]
2017-03-16 01:31:52 +03:00
Andrey Smirnov 6e96cd29dc Add bash completion to PR template [ci skip] 2017-03-16 01:30:00 +03:00
Andrey Smirnov 17044f43dc Bump Go AWS SDK to the latest version
This seems to fix `NotImplemented` S3 error
2017-03-16 01:28:44 +03:00
Andrey Smirnov 5d3b170ffc Merge pull request #497 from smira/repo-create-from-snap
Implement new command `aptly repo create ... from snapshot ...`
2017-03-16 01:12:09 +03:00
Andrey Smirnov a0f7b2242d Merge pull request #499 from sobczyk/dbgsym
include dbgsym packages
2017-03-14 22:51:24 +03:00
Szymon Sobik b8e7ad9022 update changes unit test to account for dbgsym matching 2017-03-08 10:32:11 +01:00
Szymon Sobik 1b80d55ea4 since -dbgsym is for each binary package use that for PackageQuery 2017-03-08 10:31:44 +01:00
Szymon Sobik a0832adfa5 include dbgsym packages
fixes #331
2017-03-07 17:06:59 +01:00
Andrey Smirnov f17d398e8f Implement new command aptly repo create ... from snapshot ... 2017-03-04 00:12:18 +03:00
Andrey Smirnov bc3b2ed5a8 Merge pull request #495 from apachelogger/systemd-activation
support systemd activation for `api serve`
2017-03-03 22:55:47 +03:00
Harald Sitter 07cf8925f9 support systemd activation for api serve
systemd has a feature called socket activation where initially systemd
manages and listens on ports/uds and only invokes a service when traffic
appears. to then hand over the involved sockets, systemd will pass the
relevant FDs into the invoked process and defines them in the environment.

use coreos/go-systemd to grab the active listeners passed by systemd and
use them to serve the api routes. only one listener may be specified right
now as we also only support one -listen argument for the binary.

this allows admins to craft a systemd socket and service file for aptly
where systemd manages the socket, its permission and its live time, and
lazy start aptly when needed.
2017-03-01 11:12:10 +01:00
Andrey Smirnov 564ebf3130 Merge pull request #493 from apachelogger/api-over-socket
support serving the API over unix domain socket
2017-02-28 23:41:09 +03:00
Harald Sitter dbee214259 support serving the API over unix domain socket
`unix://$PATH` as listen argument will bind aptly to a unix domain socket
rather than TCP.

This allows binding the API to a UDS rather than a port.
Since aptly has no concept of authentication or any amount of high level
API hardening one needs to bottle it up in some other manner. Binding
to a localhost port is often a step in the right direction, ultimately is
still a scary insecure setup as any user on that host getting compromised
would mean that the entire archive is compromised as well.
UDS on the other hand are basically files and have their access managed
by regular file permission. As such, binding to a socket is in fact
the least insecure way to listen as you'd have to explicitly open up the
socket permissions to an access qualified group. In the most conservative
scenario that means no one but the aptly user can talk to the API, in a
more practical setup apache might get access as well and proxy the UDS
with authentication or limited to GET operations.

Using UDS allows reducing the attack surface of the API server while
preserving all the flexibility.
2017-02-28 09:58:39 +01:00
Andrey Smirnov 6267c5cb25 Merge pull request #490 from smira/contents-low-footprint
Use temporary LevelDB to store contents index
2017-02-27 17:26:11 +03:00
Andrey Smirnov 4c06e26d85 Throttle compaction on temporary DB 2017-02-23 01:01:17 +03:00
Andrey Smirnov f2dc4eeec9 Generating contents indexes via temporary LevelDB 2017-02-21 19:09:51 +03:00
Andrey Smirnov f86e6ebf1f Merge pull request #491 from charz/master
Fix URL path for Swift.
2017-02-17 00:37:47 +03:00
Charles Hsu 0d208c93bc Merge branch 'master' of https://github.com/smira/aptly 2017-02-16 23:14:02 +08:00
Charles Hsu 485f311498 Fix URL path for Swift. 2017-02-16 23:09:18 +08:00
Andrey Smirnov 46b0d637e2 Merge pull request #484 from jola5/master
Abort serve command if rootDir is inaccessible
2017-02-15 23:54:42 +03:00
jola5 5a71847b7f Simplify test implementation 2017-02-15 20:18:47 +01:00
jola5 38a9917815 Handle dependencies in gomfile 2017-02-15 20:18:47 +01:00
jola5 4456f8da57 Refactor 2017-02-15 20:18:47 +01:00
jola5 970b1a424a Fix bugged implementation 2017-02-15 20:18:47 +01:00
jola5 edffa24658 Test startup checks for serve command 2017-02-15 20:18:47 +01:00
jola5 3040e7360a Fix golang.org/x/sys/unix dependency issue 2017-02-15 20:18:47 +01:00
jola5 b948180b4e Abort serve command if rootDir is inaccesible 2017-02-15 20:18:47 +01:00
Andrey Smirnov f58d2627c1 Add temporary DB and prefix methods to Storage 2017-02-14 02:26:32 +03:00
Andrey Smirnov ab0d77f6f9 Merge pull request #488 from smira/empty-filters
Allow filter to be empty for `aptly * search` commands
2017-02-14 01:43:46 +03:00
Andrey Smirnov 33d6cd8c0a Allow filter to be empty for aptly * search commands
Empty filter implies "select all packages".
2017-02-10 23:07:06 +03:00
Andrey Smirnov 4eef4f1803 Merge pull request #481 from smira/data-tar-gz-as-tar
Add workaround for reading data.tar.gz as data.tar
2017-01-24 20:19:50 +03:00
Andrey Smirnov c75d4c749c Add workaround for reading data.tar.gz as data.tar
It seems that in the wild there are .deb package which have
`data.tar.gz` which is actually `.tar` archive.

Add magic detection based on signature.
2017-01-24 19:30:53 +03:00
Andrey Smirnov c8a1b9a1f0 Merge pull request #482 from smira/fix-travis
Fixing Travis build
2017-01-24 19:27:58 +03:00
Andrey Smirnov d8d8973ad5 Fixing Travis build 2017-01-24 18:56:01 +03:00
Andrey Smirnov d1ded5c224 Merge pull request #480 from smira/man-generator
Add `make` automation to re-generate man page [ci skip]
2017-01-20 23:55:22 +03:00
Andrey Smirnov 155a801bc1 Add make automation to re-generate man page [ci skip]
This also updates man page with latest changes
2017-01-20 23:53:00 +03:00
Andrey Smirnov 6212b39264 Merge pull request #475 from jola5/master
Support a vertical graph layout in addition to the existing horizontal
2017-01-20 23:41:56 +03:00
jolo 92116072c2 Fix and enable broken graph layout tests 2017-01-20 02:19:45 +01:00
jolo b0ab39e07f Manually undo unintended changes 2017-01-20 02:19:44 +01:00
jola5 4bf27d1dae Merge branch 'master' into master 2017-01-19 23:07:49 +01:00
Andrey Smirnov 207ebffbb8 Merge pull request #472 from sliverc/print_sources
Print sources details of snapshots and published repositories
2017-01-19 01:05:53 +03:00
Andrey Smirnov b0dd83335f Merge branch 'master' into print_sources 2017-01-19 00:50:13 +03:00
Andrey Smirnov 8df6457931 Merge pull request #478 from smira/476-sorted-paths
Sort paths when generating checksums for `Release`/`InRelease`
2017-01-19 00:28:42 +03:00
Andrey Smirnov 7d2a396b27 Merge pull request #474 from apachelogger/support-graph.dot
Allow requesting the unrendered dot graph from the graph endpoint
2017-01-18 23:53:42 +03:00
Andrey Smirnov d5df049630 Sort paths when generating checksums for Release/InRelease 2017-01-18 23:50:22 +03:00
jolo 7c62a706c4 Disable tests failing due to inappropriate test data 2017-01-17 01:04:07 +01:00
jolo 96948d6f18 Basic test of graph layout 2017-01-17 00:46:51 +01:00
jolo 43e6498713 Add me to authors 2017-01-16 22:39:47 +01:00
jolo 91561b40f6 Change 'vertical' argument to a more generic 'layout', fix api 2017-01-16 22:13:13 +01:00
jolo 0e8ea6363a Support vertical graph layouts 2017-01-14 02:18:56 +01:00
Harald Sitter 345fa02fdc Allow requesting the unrendered dot graph from the graph endpoint
When api/graph.{dot,gv} is requested the raw string for dot gets returned.
This allows client-side rendering rather than server-side. It also makes
the optional dependency on graphivz for dot unnecessary to use the graph
endpoint.
2017-01-13 12:57:42 +01:00
Oliver Sauder 064adbae57 generate aptly.1 man page with patched ronn 2017-01-12 13:23:21 +01:00
Oliver Sauder ab458f4dfc Updated aptly man page and authors 2017-01-10 11:14:09 +01:00
Oliver Sauder 0fdee9cbf6 Added publish show command 2017-01-10 10:59:07 +01:00
Oliver Sauder 50e3e93166 print snapshot sources in snapshot show command 2017-01-09 17:29:01 +01:00
Andrey Smirnov 570835227b Merge pull request #470 from smira/templates
Add PR and issue templates
2016-12-30 17:07:54 +03:00
Andrey Smirnov 781c22e256 Add PR and issue templates 2016-12-30 00:11:45 +03:00
Andrey Smirnov babccfa21f Merge pull request #469 from smira/code-of-conduct
Add Contributor Covenant Code of Conduct [ci skip]
2016-12-29 00:03:35 +03:00
Andrey Smirnov 891113717e Add Contributor Covenant Code of Conduct [ci skip] 2016-12-29 00:01:17 +03:00
Andrey Smirnov bfb9045fa9 Merge pull request #465 from SHyx0rmZ/allow-empty-repo-edits-in-api
Allow comment and defaults to be empty when editing a repo through the API
2016-12-08 18:26:45 +03:00
Patrick Pokatilo 1c6b174b8a Make comment and defaults nullable in repo edit 2016-12-08 15:45:19 +01:00
Patrick Pokatilo fb27fb01ea Allow comment and defaults to be empty when editing a repo through the API 2016-12-08 02:14:31 +01:00
Andrey Smirnov b6327ecc43 Merge pull request #463 from sliverc/download_tries
Added --max-tries option to mirror update command
2016-11-29 17:12:36 +03:00
Oliver Sauder af71b9541c Fixing typo 2016-11-29 09:00:16 +01:00
Oliver Sauder f31b5ec3f8 Adjusted test with new maxTries param for download 2016-11-28 17:02:24 +01:00
Oliver Sauder 6becd5a3aa Added max-tries flag for mirror update 2016-11-28 17:02:24 +01:00
Andrey Smirnov 653255c728 Merge pull request #462 from smira/goxc-cleanup
Fix up build for recent versions of Go
2016-11-28 18:19:42 +03:00
Andrey Smirnov 5f0ce38161 Fix compression test for Go 1.7+ 2016-11-28 17:14:36 +03:00
Andrey Smirnov d100033b46 Fix up build for recent versions of Go
Forbid broken goxc tasks.
2016-11-28 16:37:47 +03:00
Andrey Smirnov d008cabf07 Add link to aptly_api_cli by @TimSusa 2016-11-16 02:27:01 +03:00
Andrey Smirnov f3214144a4 Merge pull request #458 from sliverc/travis-fix2
Make Travis CI be able to run on forks
2016-11-15 22:21:52 +03:00
Oliver Sauder d41841b84a Make Travis CI be able to run on forks 2016-11-15 16:19:55 +01:00
Andrey Smirnov 2a95e0eb1b Merge pull request #441 from ZettaIO/v3-auth
Identity v3 support for Swift
2016-11-11 00:19:06 +03:00
Andrey Smirnov 81f8ab2691 Merge pull request #433 from Pryz/master
Add TubeMogul Puppet module to README.rst
2016-11-09 23:55:28 +03:00
Andrey Smirnov 4e61db8d0f Fix man page (help) for aptly package show. 2016-11-09 23:07:41 +03:00
Andrey Smirnov 273d4cfa1b Merge pull request #449 from adfinis-forks/bug_415_memoryhandling
only create bzip file if needed. #415
2016-11-09 22:55:08 +03:00
Andrey Smirnov d290950d4f Merge pull request #453 from sliverc/update_leveldb
Updating goleveldb dependency
2016-11-09 22:52:29 +03:00
Oliver Sauder 2ade5b8a7f Updating leveldb fixing memory usage issue
See fix for issue https://github.com/syndtr/goleveldb/issues/138
2016-11-03 16:49:36 +01:00
Oliver Sauder fcd4429370 only create bzip file if needed. #415 2016-10-13 13:48:28 +02:00
Einar Forselv 8e62620880 Fixing tests after adding v3 swift auth 2016-09-14 20:53:01 +02:00
Einar Forselv 511fb439ac Identity v3 support for Swift
ncw/swift was bumped to latest version
2016-09-14 15:29:11 +02:00
Andrey Smirnov 34ea7e8d61 Merge pull request #418 from btkostner/test-fix
update unit tests
2016-08-22 22:25:37 +03:00
Julien Fabre 543c986885 Add TubeMogul Puppet module to README.rst 2016-08-08 09:20:28 -07:00
Blake Kostner f939532461 added exit code 2 for go 1.5 support 2016-06-22 21:59:56 -07:00
Blake Kostner aa4e225455 fix unit tests 2016-06-22 21:00:51 -07:00
Andrey Smirnov 65541a1df2 Fix system tests. 2016-05-16 13:02:00 +03:00
Andrey Smirnov 0a74b50a12 Merge branch 'dstelter-master' 2016-05-16 12:06:29 +03:00
Andrey Smirnov 902c6487da Merge branch 'master' of https://github.com/dstelter/aptly into dstelter-master 2016-05-16 12:06:00 +03:00
Andrey Smirnov 1d5b7f59cf Update system tests. 2016-05-16 11:38:20 +03:00
Daniel Stelter-Gliese 1c45c79cc1 Allow overriding architecture info from Release file
Adds a flag -force-architectures to ignore missing architectures from
mirrors. This flag can be used in cases where the mirrored repository
does not provide an "Architecture: " line.

Example Release file:
http://mitaka-jessie.pkgs.mirantis.com/debian/dists/jessie-mitaka-backports/Release
2016-05-16 03:25:00 +02:00
Andrey Smirnov 85c5aeddae Merge pull request #391 from karras/master
fix missing comma in man page example
2016-04-29 17:01:46 +03:00
Michael Hofer a95e409f52 fix missing comma in man page example 2016-04-29 09:57:06 +02:00
Andrey Smirnov 53b571d6fc Attempt to fix the build. 2016-04-25 15:13:50 +03:00
Andrey Smirnov 7a8af044ee 0.9.8~dev version. 2016-04-21 12:24:36 +03:00
Andrey Smirnov a667744502 Updte system tests. 2016-04-18 13:16:34 +03:00
Andrey Smirnov aa53b8da15 Go 1.6. 2016-04-18 12:47:00 +03:00
3468 changed files with 1993473 additions and 542 deletions
+14
View File
@@ -0,0 +1,14 @@
<!--- Provide a general summary of the issue in the Title above -->
## Detailed Description
<!--- Provide a detailed description of the change or addition you are proposing -->
## Context
<!--- Why is this change important to you? How would you use it? -->
<!--- How can it benefit other users? -->
## Possible Implementation
<!--- Not obligatory, but suggest an idea for implementing addition or change -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
+22
View File
@@ -0,0 +1,22 @@
Fixes #
## Requirements
All new code should be covered with tests, documentation should be updated. CI should pass.
## Description of the Change
<!--
Why this change is important?
-->
## Checklist
- [ ] unit-test added (if change is algorithm)
- [ ] functional test added/updated (if change is functional)
- [ ] man page updated (if applicable)
- [ ] bash completion updated (if applicable)
- [ ] documentation updated
- [ ] author name in `AUTHORS`
+5 -3
View File
@@ -27,8 +27,10 @@ coverage*.out
*.pyc *.pyc
_vendor/ xc-out/
root/
gen
man/aptly.1.html man/aptly.1.html
man/aptly.1.ronn man/aptly.1.ronn
.goxc.local.json
+12 -4
View File
@@ -2,10 +2,12 @@
"AppName": "aptly", "AppName": "aptly",
"ArtifactsDest": "xc-out/", "ArtifactsDest": "xc-out/",
"TasksExclude": [ "TasksExclude": [
"rmbin" "rmbin",
"go-test",
"go-vet"
], ],
"TasksAppend": [ "TasksAppend": [
"bintray" "bintray"
], ],
"TaskSettings": { "TaskSettings": {
"deb": { "deb": {
@@ -31,8 +33,14 @@
"downloadspage": "bintray.md" "downloadspage": "bintray.md"
} }
}, },
"ResourcesInclude": "README.rst,LICENSE,AUTHORS,man/aptly.1",
"Arch": "386 amd64", "Arch": "386 amd64",
"Os": "linux darwin freebsd", "Os": "linux darwin freebsd",
"MainDirsExclude": "man,_vendor", "MainDirsExclude": "_man,vendor",
"BuildSettings": {
"LdFlagsXVars": {
"Version": "main.Version"
}
},
"ConfigVersion": "0.9" "ConfigVersion": "0.9"
} }
+10 -3
View File
@@ -3,8 +3,9 @@ sudo: false
language: go language: go
go: go:
- 1.4 - 1.6
- 1.5 - 1.7
- 1.8
- tip - tip
addons: addons:
@@ -21,7 +22,13 @@ env:
before_install: before_install:
- virtualenv env - virtualenv env
- . env/bin/activate - . env/bin/activate
- pip install boto requests python-swiftclient - pip install six packaging appdirs
- pip install -U pip setuptools
- pip install boto requests requests-unixsocket python-swiftclient
- mkdir -p $GOPATH/src/github.com/smira
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/smira || true
- cd $GOPATH/src/github.com/smira/aptly
- make version
install: install:
- make prepare - make prepare
+4
View File
@@ -22,3 +22,7 @@ List of contributors, in chronological order:
* Phil Frost (https://github.com/bitglue) * Phil Frost (https://github.com/bitglue)
* Benoit Foucher (https://github.com/bentoi) * Benoit Foucher (https://github.com/bentoi)
* Geoffrey Thomas (https://github.com/geofft) * Geoffrey Thomas (https://github.com/geofft)
* Oliver Sauder (https://github.com/sliverc)
* Harald Sitter (https://github.com/apachelogger)
* Johannes Layher (https://github.com/jola5)
* Charles Hsu (https://github.com/charz)
+74
View File
@@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [team@aptly.info](mailto:team@aptly.info). All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
-38
View File
@@ -1,38 +0,0 @@
gom 'github.com/AlekSi/pointer', :commit => '5f6d527dae3d678b46fbb20331ddf44e2b841943'
gom 'github.com/awalterschulze/gographviz', :commit => '20d1f693416d9be045340150094aa42035a41c9e'
gom 'github.com/aws/aws-sdk-go', :commit => 'a170e9cb76475a0da7c0326a13cc2b39e9244b3b'
gom 'github.com/cheggaaa/pb', :commit => '2c1b74620cc58a81ac152ee2d322e28c806d81ed'
gom 'github.com/DisposaBoy/JsonConfigReader', :commit => '33a99fdf1d5ee1f79b5077e9c06f955ad356d5f4'
gom 'github.com/gin-gonic/gin', :commit => 'b1758d3bfa09e61ddbc1c9a627e936eec6a170de'
gom 'github.com/go-ini/ini', :commit => 'afbd495e5aaea13597b5e14fe514ddeaa4d76fc3'
gom 'github.com/jlaffaye/ftp', :commit => 'fec71e62e457557fbe85cefc847a048d57815d76'
gom 'github.com/jmespath/go-jmespath', :commit => '0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74'
gom 'github.com/julienschmidt/httprouter', :commit => '46807412fe50aaceb73bb57061c2230fd26a1640'
gom 'github.com/mattn/go-shellwords', :commit => 'c7ca6f94add751566a61cf2199e1de78d4c3eee4'
gom 'github.com/mkrautz/goar', :commit => '282caa8bd9daba480b51f1d5a988714913b97aad'
gom 'github.com/mxk/go-flowrate/flowrate', :commit => 'cca7078d478f8520f85629ad7c68962d31ed7682'
gom 'github.com/ncw/swift', :commit => '384ef27c70645e285f8bb9d02276bf654d06027e'
gom 'github.com/smira/go-aws-auth', :commit => '0070896e9d7f4f9f2d558532b2d896ce2239992a'
gom 'github.com/smira/go-xz', :commit => '0c531f070014e218b21f3cfca801cc992d52726d'
gom 'github.com/smira/commander', :commit => 'f408b00e68d5d6e21b9f18bd310978dafc604e47'
gom 'github.com/smira/flag', :commit => '357ed3e599ffcbd4aeaa828e1d10da2df3ea5107'
gom 'github.com/smira/go-ftp-protocol/protocol', :commit => '066b75c2b70dca7ae10b1b88b47534a3c31ccfaa'
gom 'github.com/smira/go-uuid/uuid', :commit => 'ed3ca8a15a931b141440a7e98e4f716eec255f7d'
gom 'github.com/smira/lzma', :commit => '7f0af6269940baa2c938fabe73e0d7ba41205683'
gom 'github.com/golang/snappy', :commit => '723cc1e459b8eea2dea4583200fd60757d40097a'
gom 'github.com/syndtr/goleveldb/leveldb', :commit => '917f41c560270110ceb73c5b38be2a9127387071'
gom 'github.com/ugorji/go/codec', :commit => '71c2886f5a673a35f909803f38ece5810165097b'
gom 'github.com/vaughan0/go-ini', :commit => 'a98ad7ee00ec53921f08832bc06ecf7fd600e6a1'
gom 'github.com/wsxiaoys/terminal/color', :commit => '5668e431776a7957528361f90ce828266c69ed08'
gom 'golang.org/x/crypto/ssh/terminal', :commit => 'a7ead6ddf06233883deca151dffaef2effbf498f'
group :test do
gom 'gopkg.in/check.v1'
end
group :development do
gom 'github.com/golang/lint/golint'
gom 'github.com/mattn/goveralls'
gom 'github.com/axw/gocov/gocov'
gom 'golang.org/x/tools/cmd/cover'
end
+28 -27
View File
@@ -1,59 +1,58 @@
GOVERSION=$(shell go version | awk '{print $$3;}') GOVERSION=$(shell go version | awk '{print $$3;}')
VERSION=$(shell git describe --tags | sed 's@^v@@' | sed 's@-@+@g')
PACKAGES=context database deb files http query swift s3 utils PACKAGES=context database deb files http query swift s3 utils
ALL_PACKAGES=api aptly context cmd console database deb files http query swift s3 utils
BINPATH=$(abspath ./_vendor/bin)
GOM_ENVIRONMENT=-test
PYTHON?=python PYTHON?=python
TESTS?=
BINPATH?=$(GOPATH)/bin
ifeq ($(GOVERSION), devel) ifeq ($(GOVERSION), devel)
TRAVIS_TARGET=coveralls TRAVIS_TARGET=coveralls
GOM_ENVIRONMENT+=-development
else else
TRAVIS_TARGET=test TRAVIS_TARGET=test
endif endif
ifeq ($(TRAVIS), true)
GOM=$(HOME)/gopath/bin/gom
else
GOM=gom
endif
all: test check system-test all: test check system-test
prepare: prepare:
go get -u github.com/mattn/gom go get -u github.com/mattn/goveralls
$(GOM) $(GOM_ENVIRONMENT) install go get -u github.com/axw/gocov/gocov
go get -u golang.org/x/tools/cmd/cover
go get -u github.com/alecthomas/gometalinter
gometalinter --install
dev:
go get -u github.com/golang/dep/...
go get -u github.com/laher/goxc
coverage.out: coverage.out:
rm -f coverage.*.out rm -f coverage.*.out
for i in $(PACKAGES); do $(GOM) test -coverprofile=coverage.$$i.out -covermode=count ./$$i; done for i in $(PACKAGES); do go test -coverprofile=coverage.$$i.out -covermode=count ./$$i; done
echo "mode: count" > coverage.out echo "mode: count" > coverage.out
grep -v -h "mode: count" coverage.*.out >> coverage.out grep -v -h "mode: count" coverage.*.out >> coverage.out
rm -f coverage.*.out rm -f coverage.*.out
coverage: coverage.out coverage: coverage.out
$(GOM) exec go tool cover -html=coverage.out go tool cover -html=coverage.out
rm -f coverage.out rm -f coverage.out
check: check:
$(GOM) exec go tool vet -all=true $(ALL_PACKAGES:%=./%) gometalinter --vendor --vendored-linters --config=linter.json ./...
$(GOM) exec golint $(ALL_PACKAGES:%=./%)
install: install:
$(GOM) build -o $(BINPATH)/aptly go install -v -ldflags "-X main.Version=$(VERSION)"
system-test: install system-test: install
if [ ! -e ~/aptly-fixture-db ]; then git clone https://github.com/aptly-dev/aptly-fixture-db.git ~/aptly-fixture-db/; fi if [ ! -e ~/aptly-fixture-db ]; then git clone https://github.com/aptly-dev/aptly-fixture-db.git ~/aptly-fixture-db/; fi
if [ ! -e ~/aptly-fixture-pool ]; then git clone https://github.com/aptly-dev/aptly-fixture-pool.git ~/aptly-fixture-pool/; fi if [ ! -e ~/aptly-fixture-pool ]; then git clone https://github.com/aptly-dev/aptly-fixture-pool.git ~/aptly-fixture-pool/; fi
PATH=$(BINPATH)/:$(PATH) $(PYTHON) system/run.py --long APTLY_VERSION=$(VERSION) PATH=$(BINPATH)/:$(PATH) $(PYTHON) system/run.py --long $(TESTS)
travis: $(TRAVIS_TARGET) system-test travis: $(TRAVIS_TARGET) check system-test
test: test:
$(GOM) test -v ./... -gocheck.v=true go test -v `go list ./... | grep -v vendor/` -gocheck.v=true
coveralls: coverage.out coveralls: coverage.out
$(GOM) exec $(BINPATH)/goveralls -service travis-ci.org -coverprofile=coverage.out -repotoken=$(COVERALLS_TOKEN) $(BINPATH)/goveralls -service travis-ci.org -coverprofile=coverage.out -repotoken=$(COVERALLS_TOKEN)
mem.png: mem.dat mem.gp mem.png: mem.dat mem.gp
gnuplot mem.gp gnuplot mem.gp
@@ -63,14 +62,10 @@ src-package:
rm -rf aptly-$(VERSION) rm -rf aptly-$(VERSION)
mkdir -p aptly-$(VERSION)/src/github.com/smira/aptly/ mkdir -p aptly-$(VERSION)/src/github.com/smira/aptly/
cd aptly-$(VERSION)/src/github.com/smira/ && git clone https://github.com/smira/aptly && cd aptly && git checkout v$(VERSION) cd aptly-$(VERSION)/src/github.com/smira/ && git clone https://github.com/smira/aptly && cd aptly && git checkout v$(VERSION)
cd aptly-$(VERSION)/src/github.com/smira/aptly && gom -production install
cd aptly-$(VERSION)/src/github.com/smira/aptly && find . \( -name .git -o -name .bzr -o -name .hg \) -print | xargs rm -rf
rm -rf aptly-$(VERSION)/src/github.com/smira/aptly/_vendor/{pkg,bin}
mkdir -p aptly-$(VERSION)/bash_completion.d mkdir -p aptly-$(VERSION)/bash_completion.d
(cd aptly-$(VERSION)/bash_completion.d && wget https://raw.github.com/aptly-dev/aptly-bash-completion/$(VERSION)/aptly) (cd aptly-$(VERSION)/bash_completion.d && wget https://raw.github.com/aptly-dev/aptly-bash-completion/$(VERSION)/aptly)
tar cyf aptly-$(VERSION)-src.tar.bz2 aptly-$(VERSION) tar cyf aptly-$(VERSION)-src.tar.bz2 aptly-$(VERSION)
rm -rf aptly-$(VERSION) rm -rf aptly-$(VERSION)
curl -T aptly-$(VERSION)-src.tar.bz2 -usmira:$(BINTRAY_KEY) https://api.bintray.com/content/smira/aptly/aptly/$(VERSION)/$(VERSION)/aptly-$(VERSION)-src.tar.bz2
goxc: goxc:
rm -rf root/ rm -rf root/
@@ -78,6 +73,12 @@ goxc:
cp man/aptly.1 root/usr/share/man/man1 cp man/aptly.1 root/usr/share/man/man1
(cd root/etc/bash_completion.d && wget https://raw.github.com/aptly-dev/aptly-bash-completion/master/aptly) (cd root/etc/bash_completion.d && wget https://raw.github.com/aptly-dev/aptly-bash-completion/master/aptly)
gzip root/usr/share/man/man1/aptly.1 gzip root/usr/share/man/man1/aptly.1
gom exec goxc -pv=$(VERSION) -max-processors=4 $(GOXC_OPTS) goxc -pv=$(VERSION) -max-processors=4 $(GOXC_OPTS)
.PHONY: coverage.out man:
make -C man
version:
@echo $(VERSION)
.PHONY: coverage.out man version
+8 -10
View File
@@ -11,8 +11,8 @@ aptly
.. image:: https://badges.gitter.im/Join Chat.svg .. image:: https://badges.gitter.im/Join Chat.svg
:target: https://gitter.im/smira/aptly?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge :target: https://gitter.im/smira/aptly?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
.. image:: http://goreportcard.com/badge/gojp/goreportcard .. image:: http://goreportcard.com/badge/smira/aptly
:target: http://goreportcard.com/report/gojp/goreportcard :target: http://goreportcard.com/report/smira/aptly
Aptly is a swiss army knife for Debian repository management. Aptly is a swiss army knife for Debian repository management.
@@ -64,19 +64,14 @@ If you would like to use nightly builds (unstable), please use following reposit
Binary executables (depends almost only on libc) are available for download from `Bintray <http://dl.bintray.com/smira/aptly/>`_. Binary executables (depends almost only on libc) are available for download from `Bintray <http://dl.bintray.com/smira/aptly/>`_.
If you have Go environment set up, you can build aptly from source by running (go 1.4+ required):: If you have Go environment set up, you can build aptly from source by running (go 1.6+ required)::
go get -u github.com/mattn/gom
mkdir -p $GOPATH/src/github.com/smira/aptly mkdir -p $GOPATH/src/github.com/smira/aptly
git clone https://github.com/smira/aptly $GOPATH/src/github.com/smira/aptly git clone https://github.com/smira/aptly $GOPATH/src/github.com/smira/aptly
cd $GOPATH/src/github.com/smira/aptly cd $GOPATH/src/github.com/smira/aptly
gom -production install make install
gom build -o $GOPATH/bin/aptly
Aptly is using `gom <https://github.com/mattn/gom>`_ to fix external dependencies, so regular ``go get github.com/smira/aptly`` Binary would be installed to ```$GOPATH/bin/aptly``.
should work as well, but might fail or produce different result (if external libraries got updated).
If you don't have Go installed (or older version), you can easily install Go using `gvm <https://github.com/moovweb/gvm/>`_.
Integrations Integrations
------------ ------------
@@ -98,6 +93,8 @@ With configuration management systems:
(Heavy Water Operations, LLC) (Heavy Water Operations, LLC)
- `Puppet module <https://github.com/alphagov/puppet-aptly>`_ by - `Puppet module <https://github.com/alphagov/puppet-aptly>`_ by
Government Digital Services Government Digital Services
- `Puppet module <https://github.com/tubemogul/puppet-aptly>`_ by
TubeMogul
- `SaltStack Formula <https://github.com/saltstack-formulas/aptly-formula>`_ by - `SaltStack Formula <https://github.com/saltstack-formulas/aptly-formula>`_ by
Forrest Alvarez and Brian Jackson Forrest Alvarez and Brian Jackson
- `Ansible role <https://github.com/aioue/ansible-role-aptly>`_ by Tom Paine - `Ansible role <https://github.com/aioue/ansible-role-aptly>`_ by Tom Paine
@@ -105,6 +102,7 @@ With configuration management systems:
CLI for aptly API: CLI for aptly API:
- `Ruby aptly CLI/library <https://github.com/sepulworld/aptly_cli>`_ by Zane Williamson - `Ruby aptly CLI/library <https://github.com/sepulworld/aptly_cli>`_ by Zane Williamson
- `Python aptly CLI (good for CI) <https://github.com/TimSusa/aptly_api_cli>`_ by Tim Susa
Scala sbt: Scala sbt:
+5 -6
View File
@@ -2,17 +2,17 @@ package main
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/cmd"
"github.com/smira/commander"
"github.com/smira/flag"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"text/template" "text/template"
"github.com/smira/aptly/cmd"
"github.com/smira/commander"
"github.com/smira/flag"
) )
func allFlags(flags *flag.FlagSet) []*flag.Flag { func allFlags(flags *flag.FlagSet) []*flag.Flag {
@@ -55,8 +55,7 @@ func main() {
command.UsageLine = "aptly" command.UsageLine = "aptly"
command.Dispatch(nil) command.Dispatch(nil)
_, _File, _, _ := runtime.Caller(0) _File, _ := filepath.Abs("./man")
_File, _ = filepath.Abs(_File)
templ := template.New("man").Funcs(template.FuncMap{ templ := template.New("man").Funcs(template.FuncMap{
"allFlags": allFlags, "allFlags": allFlags,
+7 -6
View File
@@ -3,12 +3,13 @@ package api
import ( import (
"fmt" "fmt"
"sort"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"sort"
"time"
) )
// Lock order acquisition (canonical): // Lock order acquisition (canonical):
@@ -23,8 +24,8 @@ func apiVersion(c *gin.Context) {
} }
const ( const (
ACQUIREDB = iota acquiredb = iota
RELEASEDB releasedb
) )
// Flushes all collections which cache in-memory objects // Flushes all collections which cache in-memory objects
@@ -80,14 +81,14 @@ func acquireDatabase(requests chan int, acks chan error) {
for { for {
request := <-requests request := <-requests
switch request { switch request {
case ACQUIREDB: case acquiredb:
if clients == 0 { if clients == 0 {
acks <- context.ReOpenDatabase() acks <- context.ReOpenDatabase()
} else { } else {
acks <- nil acks <- nil
} }
clients++ clients++
case RELEASEDB: case releasedb:
clients-- clients--
if clients == 0 { if clients == 0 {
flushColections() flushColections()
+2 -1
View File
@@ -2,11 +2,12 @@ package api
import ( import (
"fmt" "fmt"
"github.com/gin-gonic/gin"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/gin-gonic/gin"
) )
func verifyPath(path string) bool { func verifyPath(path string) bool {
+13 -4
View File
@@ -3,15 +3,16 @@ package api
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/gin-gonic/gin"
"github.com/smira/aptly/deb"
"io" "io"
"mime" "mime"
"os" "os"
"os/exec" "os/exec"
"github.com/gin-gonic/gin"
"github.com/smira/aptly/deb"
) )
// GET /api/graph.:ext // GET /api/graph.:ext?layout=[vertical|horizontal(default)]
func apiGraph(c *gin.Context) { func apiGraph(c *gin.Context) {
var ( var (
err error err error
@@ -19,6 +20,7 @@ func apiGraph(c *gin.Context) {
) )
ext := c.Params.ByName("ext") ext := c.Params.ByName("ext")
layout := c.Request.URL.Query().Get("layout")
factory := context.CollectionFactory() factory := context.CollectionFactory()
@@ -31,7 +33,7 @@ func apiGraph(c *gin.Context) {
factory.PublishedRepoCollection().RLock() factory.PublishedRepoCollection().RLock()
defer factory.PublishedRepoCollection().RUnlock() defer factory.PublishedRepoCollection().RUnlock()
graph, err := deb.BuildGraph(factory) graph, err := deb.BuildGraph(factory, layout)
if err != nil { if err != nil {
c.JSON(500, err) c.JSON(500, err)
return return
@@ -39,6 +41,13 @@ func apiGraph(c *gin.Context) {
buf := bytes.NewBufferString(graph.String()) buf := bytes.NewBufferString(graph.String())
if ext == "dot" || ext == "gv" {
// If the raw dot data is requested, return it as string.
// This allows client-side rendering rather than server-side.
c.String(200, buf.String())
return
}
command := exec.Command("dot", "-T"+ext) command := exec.Command("dot", "-T"+ext)
command.Stderr = os.Stderr command.Stderr = os.Stderr
+2 -1
View File
@@ -2,10 +2,11 @@ package api
import ( import (
"fmt" "fmt"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"strings"
) )
// SigningOptions is a shared between publish API GPG options structure // SigningOptions is a shared between publish API GPG options structure
+12 -11
View File
@@ -2,13 +2,14 @@ package api
import ( import (
"fmt" "fmt"
"os"
"path/filepath"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"os"
"path/filepath"
) )
// GET /api/repos // GET /api/repos
@@ -60,9 +61,9 @@ func apiReposCreate(c *gin.Context) {
// PUT /api/repos/:name // PUT /api/repos/:name
func apiReposEdit(c *gin.Context) { func apiReposEdit(c *gin.Context) {
var b struct { var b struct {
Comment string Comment *string
DefaultDistribution string DefaultDistribution *string
DefaultComponent string DefaultComponent *string
} }
if !c.Bind(&b) { if !c.Bind(&b) {
@@ -79,14 +80,14 @@ func apiReposEdit(c *gin.Context) {
return return
} }
if b.Comment != "" { if b.Comment != nil {
repo.Comment = b.Comment repo.Comment = *b.Comment
} }
if b.DefaultDistribution != "" { if b.DefaultDistribution != nil {
repo.DefaultDistribution = b.DefaultDistribution repo.DefaultDistribution = *b.DefaultDistribution
} }
if b.DefaultComponent != "" { if b.DefaultComponent != nil {
repo.DefaultComponent = b.DefaultComponent repo.DefaultComponent = *b.DefaultComponent
} }
err = collection.Update(repo) err = collection.Update(repo)
+4 -3
View File
@@ -1,9 +1,10 @@
package api package api
import ( import (
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
ctx "github.com/smira/aptly/context" ctx "github.com/smira/aptly/context"
"net/http"
) )
var context *ctx.AptlyContext var context *ctx.AptlyContext
@@ -26,14 +27,14 @@ func Router(c *ctx.AptlyContext) http.Handler {
go cacheFlusher(requests, acks) go cacheFlusher(requests, acks)
router.Use(func(c *gin.Context) { router.Use(func(c *gin.Context) {
requests <- ACQUIREDB requests <- acquiredb
err := <-acks err := <-acks
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
return return
} }
defer func() { defer func() {
requests <- RELEASEDB requests <- releasedb
err = <-acks err = <-acks
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
+1
View File
@@ -2,6 +2,7 @@ package api
import ( import (
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
+3 -2
View File
@@ -3,8 +3,9 @@
package aptly package aptly
import ( import (
"github.com/smira/aptly/utils"
"io" "io"
"github.com/smira/aptly/utils"
) )
// PackagePool is asbtraction of package pool storage. // PackagePool is asbtraction of package pool storage.
@@ -82,7 +83,7 @@ type Downloader interface {
// Download starts new download task // Download starts new download task
Download(url string, destination string, result chan<- error) Download(url string, destination string, result chan<- error)
// DownloadWithChecksum starts new download task with checksum verification // DownloadWithChecksum starts new download task with checksum verification
DownloadWithChecksum(url string, destination string, result chan<- error, expected utils.ChecksumInfo, ignoreMismatch bool) DownloadWithChecksum(url string, destination string, result chan<- error, expected utils.ChecksumInfo, ignoreMismatch bool, maxTries int)
// Pause pauses task processing // Pause pauses task processing
Pause() Pause()
// Resume resumes task processing // Resume resumes task processing
+3 -3
View File
@@ -1,7 +1,7 @@
package aptly package aptly
// Version of aptly // Version of aptly (filled in at link time)
const Version = "0.9.7" var Version string
// Enable debugging features? // EnableDebug triggers some debugging features
const EnableDebug = false const EnableDebug = false
+57 -4
View File
@@ -2,10 +2,16 @@ package cmd
import ( import (
"fmt" "fmt"
"net"
"net/http"
"net/url"
"os"
"github.com/smira/aptly/api" "github.com/smira/aptly/api"
"github.com/smira/aptly/systemd/activation"
"github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"net/http"
) )
func aptlyAPIServe(cmd *commander.Command, args []string) error { func aptlyAPIServe(cmd *commander.Command, args []string) error {
@@ -18,10 +24,53 @@ func aptlyAPIServe(cmd *commander.Command, args []string) error {
return commander.ErrCommandError return commander.ErrCommandError
} }
listen := context.Flags().Lookup("listen").Value.String() // There are only two working options for aptly's rootDir:
// 1. rootDir does not exist, then we'll create it
// 2. rootDir exists and is writable
// anything else must fail.
// E.g.: Running the service under a different user may lead to a rootDir
// that exists but is not usable due to access permissions.
err = utils.DirIsAccessible(context.Config().RootDir)
if err != nil {
return err
}
// Try to recycle systemd fds for listening
listeners, err := activation.Listeners(true)
if len(listeners) > 1 {
panic("Got more than 1 listener from systemd. This is currently not supported!")
}
if err == nil && len(listeners) == 1 {
listener := listeners[0]
defer listener.Close()
fmt.Printf("\nTaking over web server at: %s (press Ctrl+C to quit)...\n", listener.Addr().String())
err = http.Serve(listener, api.Router(context))
if err != nil {
return fmt.Errorf("unable to serve: %s", err)
}
return nil
}
// If there are none: use the listen argument.
listen := context.Flags().Lookup("listen").Value.String()
fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen) fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen)
listenURL, err := url.Parse(listen)
if err == nil && listenURL.Scheme == "unix" {
file := listenURL.Path
os.Remove(file)
listener, err := net.Listen("unix", file)
if err != nil {
return fmt.Errorf("failed to listen on: %s\n%s", file, err)
}
defer listener.Close()
err = http.Serve(listener, api.Router(context))
if err != nil {
return fmt.Errorf("unable to serve: %s", err)
}
return nil
}
err = http.ListenAndServe(listen, api.Router(context)) err = http.ListenAndServe(listen, api.Router(context))
if err != nil { if err != nil {
return fmt.Errorf("unable to serve: %s", err) return fmt.Errorf("unable to serve: %s", err)
@@ -36,16 +85,20 @@ func makeCmdAPIServe() *commander.Command {
UsageLine: "serve", UsageLine: "serve",
Short: "start API HTTP service", Short: "start API HTTP service",
Long: ` Long: `
Stat HTTP server with aptly REST API. Start HTTP server with aptly REST API. The server can listen to either a port
or Unix domain socket. When using a socket, Aptly will fully manage the socket
file. This command also supports taking over from a systemd file descriptors to
enable systemd socket activation.
Example: Example:
$ aptly api serve -listen=:8080 $ aptly api serve -listen=:8080
$ aptly api serve -listen=unix:///tmp/aptly.sock
`, `,
Flag: *flag.NewFlagSet("aptly-serve", flag.ExitOnError), Flag: *flag.NewFlagSet("aptly-serve", flag.ExitOnError),
} }
cmd.Flag.String("listen", ":8080", "host:port for HTTP listening") cmd.Flag.String("listen", ":8080", "host:port for HTTP listening or unix://path to listen on a Unix domain socket")
cmd.Flag.Bool("no-lock", false, "don't lock the database") cmd.Flag.Bool("no-lock", false, "don't lock the database")
return cmd return cmd
+4 -3
View File
@@ -4,13 +4,14 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"text/template"
"time"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
"text/template"
"time"
) )
// ListPackagesRefList shows list of packages in PackageRefList // ListPackagesRefList shows list of packages in PackageRefList
+1
View File
@@ -3,6 +3,7 @@ package cmd
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
) )
+4 -3
View File
@@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"sort"
"strings"
) )
// aptly db cleanup // aptly db cleanup
@@ -153,7 +154,7 @@ func aptlyDbCleanup(cmd *commander.Command, args []string) error {
context.Progress().ColoredPrintf("@{w!}Loading list of all packages...@|") context.Progress().ColoredPrintf("@{w!}Loading list of all packages...@|")
allPackageRefs := context.CollectionFactory().PackageCollection().AllPackageRefs() allPackageRefs := context.CollectionFactory().PackageCollection().AllPackageRefs()
toDelete := allPackageRefs.Substract(existingPackageRefs) toDelete := allPackageRefs.Subtract(existingPackageRefs)
// delete packages that are no longer referenced // delete packages that are no longer referenced
context.Progress().ColoredPrintf("@{r!}Deleting unreferenced packages (%d)...@|", toDelete.Len()) context.Progress().ColoredPrintf("@{r!}Deleting unreferenced packages (%d)...@|", toDelete.Len())
+43 -7
View File
@@ -3,14 +3,18 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/smira/aptly/deb"
"github.com/smira/aptly/utils"
"github.com/smira/commander"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"strings"
"time"
"github.com/smira/aptly/deb"
"github.com/smira/aptly/utils"
"github.com/smira/commander"
) )
func aptlyGraph(cmd *commander.Command, args []string) error { func aptlyGraph(cmd *commander.Command, args []string) error {
@@ -21,8 +25,11 @@ func aptlyGraph(cmd *commander.Command, args []string) error {
return commander.ErrCommandError return commander.ErrCommandError
} }
layout := context.Flags().Lookup("layout").Value.String()
fmt.Printf("Generating graph...\n") fmt.Printf("Generating graph...\n")
graph, err := deb.BuildGraph(context.CollectionFactory()) graph, err := deb.BuildGraph(context.CollectionFactory(), layout)
if err != nil { if err != nil {
return err return err
} }
@@ -73,23 +80,51 @@ func aptlyGraph(cmd *commander.Command, args []string) error {
return err return err
} }
defer func() {
_ = os.Remove(tempfilename)
}()
if output != "" { if output != "" {
err = utils.CopyFile(tempfilename, output) err = utils.CopyFile(tempfilename, output)
if err != nil { if err != nil {
return fmt.Errorf("unable to copy %s -> %s: %s", tempfilename, output, err) return fmt.Errorf("unable to copy %s -> %s: %s", tempfilename, output, err)
} }
_ = os.Remove(tempfilename)
fmt.Printf("Output saved to %s\n", output) fmt.Printf("Output saved to %s\n", output)
} else { } else {
fmt.Printf("Rendered to %s file: %s, trying to open it...\n", format, tempfilename) command := getOpenCommand()
fmt.Printf("Rendered to %s file: %s, trying to open it with: %s %s...\n", format, tempfilename, command, tempfilename)
_ = exec.Command("open", tempfilename).Run() args := strings.Split(command, " ")
viewer := exec.Command(args[0], append(args[1:], tempfilename)...)
viewer.Stderr = os.Stderr
if err = viewer.Start(); err == nil {
// Wait for a second so that the visualizer has a chance to
// open the input file. This needs to be done even if we're
// waiting for the visualizer as it can be just a wrapper that
// spawns a browser tab and returns right away.
defer func(t <-chan time.Time) {
<-t
}(time.After(time.Second))
}
} }
return err return err
} }
// getOpenCommand tries to guess command to open image for OS
func getOpenCommand() string {
switch runtime.GOOS {
case "darwin":
return "/usr/bin/open"
case "windows":
return "cmd /c start"
default:
return "xdg-open"
}
}
func makeCmdGraph() *commander.Command { func makeCmdGraph() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlyGraph, Run: aptlyGraph,
@@ -108,6 +143,7 @@ Example:
cmd.Flag.String("format", "png", "render graph to specified format (png, svg, pdf, etc.)") cmd.Flag.String("format", "png", "render graph to specified format (png, svg, pdf, etc.)")
cmd.Flag.String("output", "", "specify output filename, default is to open result in viewer") cmd.Flag.String("output", "", "specify output filename, default is to open result in viewer")
cmd.Flag.String("layout", "horizontal", "create a more 'vertical' or a more 'horizontal' graph layout")
return cmd return cmd
} }
+2 -1
View File
@@ -1,10 +1,11 @@
package cmd package cmd
import ( import (
"strings"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func getVerifier(flags *flag.FlagSet) (utils.Verifier, error) { func getVerifier(flags *flag.FlagSet) (utils.Verifier, error) {
+4 -1
View File
@@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func aptlyMirrorCreate(cmd *commander.Command, args []string) error { func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
@@ -43,6 +44,7 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
repo.Filter = context.Flags().Lookup("filter").Value.String() repo.Filter = context.Flags().Lookup("filter").Value.String()
repo.FilterWithDeps = context.Flags().Lookup("filter-with-deps").Value.Get().(bool) repo.FilterWithDeps = context.Flags().Lookup("filter-with-deps").Value.Get().(bool)
repo.SkipComponentCheck = context.Flags().Lookup("force-components").Value.Get().(bool) repo.SkipComponentCheck = context.Flags().Lookup("force-components").Value.Get().(bool)
repo.SkipArchitectureCheck = context.Flags().Lookup("force-architectures").Value.Get().(bool)
if repo.Filter != "" { if repo.Filter != "" {
_, err = query.Parse(repo.Filter) _, err = query.Parse(repo.Filter)
@@ -97,6 +99,7 @@ Example:
cmd.Flag.String("filter", "", "filter packages in mirror") cmd.Flag.String("filter", "", "filter packages in mirror")
cmd.Flag.Bool("filter-with-deps", false, "when filtering, include dependencies of matching packages as well") cmd.Flag.Bool("filter-with-deps", false, "when filtering, include dependencies of matching packages as well")
cmd.Flag.Bool("force-components", false, "(only with component list) skip check that requested components are listed in Release file") cmd.Flag.Bool("force-components", false, "(only with component list) skip check that requested components are listed in Release file")
cmd.Flag.Bool("force-architectures", false, "(only with architecture list) skip check that requested architectures are listed in Release file")
cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)") cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)")
return cmd return cmd
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"sort"
) )
func aptlyMirrorList(cmd *commander.Command, args []string) error { func aptlyMirrorList(cmd *commander.Command, args []string) error {
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+3 -1
View File
@@ -8,11 +8,13 @@ import (
func makeCmdMirrorSearch() *commander.Command { func makeCmdMirrorSearch() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlySnapshotMirrorRepoSearch, Run: aptlySnapshotMirrorRepoSearch,
UsageLine: "search <name> <package-query>", UsageLine: "search <name> [<package-query>]",
Short: "search mirror for packages matching query", Short: "search mirror for packages matching query",
Long: ` Long: `
Command search displays list of packages in mirror that match package query Command search displays list of packages in mirror that match package query
If query is not specified, all the packages are displayed.
Example: Example:
$ aptly mirror search wheezy-main '$Architecture (i386), Name (% *-dev)' $ aptly mirror search wheezy-main '$Architecture (i386), Name (% *-dev)'
+2 -1
View File
@@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func aptlyMirrorShow(cmd *commander.Command, args []string) error { func aptlyMirrorShow(cmd *commander.Command, args []string) error {
+11 -8
View File
@@ -2,14 +2,15 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"os/signal"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
"os/signal"
"strings"
) )
func aptlyMirrorUpdate(cmd *commander.Command, args []string) error { func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
@@ -40,6 +41,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
} }
ignoreMismatch := context.Flags().Lookup("ignore-checksums").Value.Get().(bool) ignoreMismatch := context.Flags().Lookup("ignore-checksums").Value.Get().(bool)
maxTries := context.Flags().Lookup("max-tries").Value.Get().(int)
verifier, err := getVerifier(context.Flags()) verifier, err := getVerifier(context.Flags())
if err != nil { if err != nil {
@@ -52,7 +54,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
} }
context.Progress().Printf("Downloading & parsing package files...\n") context.Progress().Printf("Downloading & parsing package files...\n")
err = repo.DownloadPackageIndexes(context.Progress(), context.Downloader(), context.CollectionFactory(), ignoreMismatch) err = repo.DownloadPackageIndexes(context.Progress(), context.Downloader(), context.CollectionFactory(), ignoreMismatch, maxTries)
if err != nil { if err != nil {
return fmt.Errorf("unable to update: %s", err) return fmt.Errorf("unable to update: %s", err)
} }
@@ -87,7 +89,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
defer func() { defer func() {
// on any interruption, unlock the mirror // on any interruption, unlock the mirror
err := context.ReOpenDatabase() err = context.ReOpenDatabase()
if err == nil { if err == nil {
repo.MarkAsIdle() repo.MarkAsIdle()
context.CollectionFactory().RemoteRepoCollection().Update(repo) context.CollectionFactory().RemoteRepoCollection().Update(repo)
@@ -121,7 +123,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
// In separate goroutine (to avoid blocking main), push queue to downloader // In separate goroutine (to avoid blocking main), push queue to downloader
go func() { go func() {
for _, task := range queue { for _, task := range queue {
context.Downloader().DownloadWithChecksum(repo.PackageURL(task.RepoURI).String(), task.DestinationPath, ch, task.Checksums, ignoreMismatch) context.Downloader().DownloadWithChecksum(repo.PackageURL(task.RepoURI).String(), task.DestinationPath, ch, task.Checksums, ignoreMismatch, maxTries)
} }
// We don't need queue after this point // We don't need queue after this point
@@ -129,7 +131,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
}() }()
// Wait for all downloads to finish // Wait for all downloads to finish
errors := make([]string, 0) var errors []string
for count > 0 { for count > 0 {
select { select {
@@ -148,7 +150,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
signal.Stop(sigch) signal.Stop(sigch)
if len(errors) > 0 { if len(errors) > 0 {
return fmt.Errorf("unable to update: download errors:\n %s\n", strings.Join(errors, "\n ")) return fmt.Errorf("unable to update: download errors:\n %s", strings.Join(errors, "\n "))
} }
err = context.ReOpenDatabase() err = context.ReOpenDatabase()
@@ -187,6 +189,7 @@ Example:
cmd.Flag.Bool("ignore-checksums", false, "ignore checksum mismatches while downloading package files and metadata") cmd.Flag.Bool("ignore-checksums", false, "ignore checksum mismatches while downloading package files and metadata")
cmd.Flag.Bool("ignore-signatures", false, "disable verification of Release file signatures") cmd.Flag.Bool("ignore-signatures", false, "disable verification of Release file signatures")
cmd.Flag.Int64("download-limit", 0, "limit download speed (kbytes/sec)") cmd.Flag.Int64("download-limit", 0, "limit download speed (kbytes/sec)")
cmd.Flag.Int("max-tries", 1, "max download tries till process fails with download error")
cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)") cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)")
return cmd return cmd
+19 -7
View File
@@ -2,21 +2,31 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
func aptlyPackageSearch(cmd *commander.Command, args []string) error { func aptlyPackageSearch(cmd *commander.Command, args []string) error {
var err error var (
if len(args) != 1 { err error
q deb.PackageQuery
)
if len(args) > 1 {
cmd.Usage() cmd.Usage()
return commander.ErrCommandError return commander.ErrCommandError
} }
q, err := query.Parse(args[0]) if len(args) == 1 {
if err != nil { q, err = query.Parse(args[0])
return fmt.Errorf("unable to search: %s", err) if err != nil {
return fmt.Errorf("unable to search: %s", err)
}
} else {
q = &deb.MatchAllQuery{}
} }
result := q.Query(context.CollectionFactory().PackageCollection()) result := q.Query(context.CollectionFactory().PackageCollection())
@@ -33,10 +43,12 @@ func aptlyPackageSearch(cmd *commander.Command, args []string) error {
func makeCmdPackageSearch() *commander.Command { func makeCmdPackageSearch() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlyPackageSearch, Run: aptlyPackageSearch,
UsageLine: "search <package-query>", UsageLine: "search [<package-query>]",
Short: "search for packages matching query", Short: "search for packages matching query",
Long: ` Long: `
Command search displays list of packages in whole DB that match package query Command search displays list of packages in whole DB that match package query.
If query is not specified, all the packages are displayed.
Example: Example:
+3 -2
View File
@@ -3,11 +3,12 @@ package cmd
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"os"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
) )
func printReferencesTo(p *deb.Package) (err error) { func printReferencesTo(p *deb.Package) (err error) {
@@ -125,7 +126,7 @@ inclusion into mirrors/snapshots/local repos is shown.
Example: Example:
$ aptly package show nginx-light_1.2.1-2.2+wheezy2_i386' $ aptly package show 'nginx-light_1.2.1-2.2+wheezy2_i386'
`, `,
Flag: *flag.NewFlagSet("aptly-package-show", flag.ExitOnError), Flag: *flag.NewFlagSet("aptly-package-show", flag.ExitOnError),
} }
+1
View File
@@ -37,6 +37,7 @@ func makeCmdPublish() *commander.Command {
makeCmdPublishSnapshot(), makeCmdPublishSnapshot(),
makeCmdPublishSwitch(), makeCmdPublishSwitch(),
makeCmdPublishUpdate(), makeCmdPublishUpdate(),
makeCmdPublishShow(),
}, },
} }
} }
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"sort"
) )
func aptlyPublishList(cmd *commander.Command, args []string) error { func aptlyPublishList(cmd *commander.Command, args []string) error {
+81
View File
@@ -0,0 +1,81 @@
package cmd
import (
"fmt"
"strings"
"github.com/smira/aptly/deb"
"github.com/smira/commander"
)
func aptlyPublishShow(cmd *commander.Command, args []string) error {
var err error
if len(args) < 1 || len(args) > 2 {
cmd.Usage()
return commander.ErrCommandError
}
distribution := args[0]
param := "."
if len(args) == 2 {
param = args[1]
}
storage, prefix := deb.ParsePrefix(param)
repo, err := context.CollectionFactory().PublishedRepoCollection().ByStoragePrefixDistribution(storage, prefix, distribution)
if err != nil {
return fmt.Errorf("unable to show: %s", err)
}
if repo.Storage != "" {
fmt.Printf("Storage: %s\n", repo.Storage)
}
fmt.Printf("Prefix: %s\n", repo.Prefix)
if repo.Distribution != "" {
fmt.Printf("Distribution: %s\n", repo.Distribution)
}
fmt.Printf("Architectures: %s\n", strings.Join(repo.Architectures, " "))
fmt.Printf("Sources:\n")
for component, sourceID := range repo.Sources {
var name string
if repo.SourceKind == "snapshot" {
source, err := context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
if err != nil {
continue
}
name = source.Name
} else if repo.SourceKind == "local" {
source, err := context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
if err != nil {
continue
}
name = source.Name
}
if name != "" {
fmt.Printf(" %s: %s [%s]\n", component, name, repo.SourceKind)
}
}
return err
}
func makeCmdPublishShow() *commander.Command {
cmd := &commander.Command{
Run: aptlyPublishShow,
UsageLine: "show <distribution> [[<endpoint>:]<prefix>]",
Short: "shows details of published repository",
Long: `
Command show displays full information of a published repository.
Example:
$ aptly publish show wheezy
`,
}
return cmd
}
+2 -1
View File
@@ -2,12 +2,13 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error { func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
+2 -1
View File
@@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func aptlyPublishSwitch(cmd *commander.Command, args []string) error { func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
+2 -1
View File
@@ -2,12 +2,13 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
) )
func aptlyRepoAdd(cmd *commander.Command, args []string) error { func aptlyRepoAdd(cmd *commander.Command, args []string) error {
+24 -2
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
@@ -9,7 +10,7 @@ import (
func aptlyRepoCreate(cmd *commander.Command, args []string) error { func aptlyRepoCreate(cmd *commander.Command, args []string) error {
var err error var err error
if len(args) != 1 { if !(len(args) == 1 || (len(args) == 4 && args[1] == "from" && args[2] == "snapshot")) {
cmd.Usage() cmd.Usage()
return commander.ErrCommandError return commander.ErrCommandError
} }
@@ -26,6 +27,22 @@ func aptlyRepoCreate(cmd *commander.Command, args []string) error {
} }
} }
if len(args) == 4 {
var snapshot *deb.Snapshot
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(args[3])
if err != nil {
return fmt.Errorf("unable to load source snapshot: %s", err)
}
err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to load source snapshot: %s", err)
}
repo.UpdateRefList(snapshot.RefList())
}
err = context.CollectionFactory().LocalRepoCollection().Add(repo) err = context.CollectionFactory().LocalRepoCollection().Add(repo)
if err != nil { if err != nil {
return fmt.Errorf("unable to add local repo: %s", err) return fmt.Errorf("unable to add local repo: %s", err)
@@ -38,16 +55,21 @@ func aptlyRepoCreate(cmd *commander.Command, args []string) error {
func makeCmdRepoCreate() *commander.Command { func makeCmdRepoCreate() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlyRepoCreate, Run: aptlyRepoCreate,
UsageLine: "create <name>", UsageLine: "create <name> [ from snapshot <snapshot> ]",
Short: "create local repository", Short: "create local repository",
Long: ` Long: `
Create local package repository. Repository would be empty when Create local package repository. Repository would be empty when
created, packages could be added from files, copied or moved from created, packages could be added from files, copied or moved from
another local repository or imported from the mirror. another local repository or imported from the mirror.
If local package repository is created from snapshot, repo initial
contents are copied from snapsot contents.
Example: Example:
$ aptly repo create testing $ aptly repo create testing
$ aptly repo create mysql35 from snapshot mysql-35-2017
`, `,
Flag: *flag.NewFlagSet("aptly-repo-create", flag.ExitOnError), Flag: *flag.NewFlagSet("aptly-repo-create", flag.ExitOnError),
} }
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/AlekSi/pointer" "github.com/AlekSi/pointer"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
+4 -3
View File
@@ -3,15 +3,16 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"path/filepath"
"text/template"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
"path/filepath"
"text/template"
) )
func aptlyRepoInclude(cmd *commander.Command, args []string) error { func aptlyRepoInclude(cmd *commander.Command, args []string) error {
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"sort"
) )
func aptlyRepoList(cmd *commander.Command, args []string) error { func aptlyRepoList(cmd *commander.Command, args []string) error {
+2 -1
View File
@@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"sort"
) )
func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error { func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+3 -1
View File
@@ -8,11 +8,13 @@ import (
func makeCmdRepoSearch() *commander.Command { func makeCmdRepoSearch() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlySnapshotMirrorRepoSearch, Run: aptlySnapshotMirrorRepoSearch,
UsageLine: "search <name> <package-query>", UsageLine: "search <name> [<package-query>]",
Short: "search repo for packages matching query", Short: "search repo for packages matching query",
Long: ` Long: `
Command search displays list of packages in local repository that match package query Command search displays list of packages in local repository that match package query
If query is not specified, all the packages are displayed.
Example: Example:
$ aptly repo search my-software '$Architecture (i386), Name (% *-dev)' $ aptly repo search my-software '$Architecture (i386), Name (% *-dev)'
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
ctx "github.com/smira/aptly/context" ctx "github.com/smira/aptly/context"
"github.com/smira/commander" "github.com/smira/commander"
"os"
) )
// Run runs single command starting from root cmd with args, optionally initializing context // Run runs single command starting from root cmd with args, optionally initializing context
+17 -5
View File
@@ -2,16 +2,17 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb"
"github.com/smira/aptly/utils"
"github.com/smira/commander"
"github.com/smira/flag"
"net" "net"
"net/http" "net/http"
"os" "os"
"sort" "sort"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/deb"
"github.com/smira/aptly/utils"
"github.com/smira/commander"
"github.com/smira/flag"
) )
func aptlyServe(cmd *commander.Command, args []string) error { func aptlyServe(cmd *commander.Command, args []string) error {
@@ -22,6 +23,17 @@ func aptlyServe(cmd *commander.Command, args []string) error {
return commander.ErrCommandError return commander.ErrCommandError
} }
// There are only two working options for aptly's rootDir:
// 1. rootDir does not exist, then we'll create it
// 2. rootDir exists and is writable
// anything else must fail.
// E.g.: Running the service under a different user may lead to a rootDir
// that exists but is not usable due to access permissions.
err = utils.DirIsAccessible(context.Config().RootDir)
if err != nil {
return err
}
if context.CollectionFactory().PublishedRepoCollection().Len() == 0 { if context.CollectionFactory().PublishedRepoCollection().Len() == 0 {
fmt.Printf("No published repositories, unable to serve.\n") fmt.Printf("No published repositories, unable to serve.\n")
return nil return nil
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
+3 -2
View File
@@ -2,12 +2,13 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"sort"
"strings"
) )
func aptlySnapshotFilter(cmd *commander.Command, args []string) error { func aptlySnapshotFilter(cmd *commander.Command, args []string) error {
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"strings"
) )
func aptlySnapshotMerge(cmd *commander.Command, args []string) error { func aptlySnapshotMerge(cmd *commander.Command, args []string) error {
+3 -2
View File
@@ -2,12 +2,13 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"strings"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"sort"
"strings"
) )
func aptlySnapshotPull(cmd *commander.Command, args []string) error { func aptlySnapshotPull(cmd *commander.Command, args []string) error {
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
) )
+18 -7
View File
@@ -2,16 +2,21 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/aptly/query" "github.com/smira/aptly/query"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"sort"
) )
func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error { func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error {
var err error var (
if len(args) != 2 { err error
q deb.PackageQuery
)
if len(args) < 1 || len(args) > 2 {
cmd.Usage() cmd.Usage()
return commander.ErrCommandError return commander.ErrCommandError
} }
@@ -68,9 +73,13 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
list.PrepareIndex() list.PrepareIndex()
q, err := query.Parse(args[1]) if len(args) == 2 {
if err != nil { q, err = query.Parse(args[1])
return fmt.Errorf("unable to search: %s", err) if err != nil {
return fmt.Errorf("unable to search: %s", err)
}
} else {
q = &deb.MatchAllQuery{}
} }
withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool) withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)
@@ -109,11 +118,13 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
func makeCmdSnapshotSearch() *commander.Command { func makeCmdSnapshotSearch() *commander.Command {
cmd := &commander.Command{ cmd := &commander.Command{
Run: aptlySnapshotMirrorRepoSearch, Run: aptlySnapshotMirrorRepoSearch,
UsageLine: "search <name> <package-query>", UsageLine: "search <name> [<package-query>]",
Short: "search snapshot for packages matching query", Short: "search snapshot for packages matching query",
Long: ` Long: `
Command search displays list of packages in snapshot that match package query Command search displays list of packages in snapshot that match package query
If query is not specified, all the packages are displayed.
Example: Example:
$ aptly snapshot search wheezy-main '$Architecture (i386), Name (% *-dev)' $ aptly snapshot search wheezy-main '$Architecture (i386), Name (% *-dev)'
+30
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
) )
@@ -29,6 +30,35 @@ func aptlySnapshotShow(cmd *commander.Command, args []string) error {
fmt.Printf("Created At: %s\n", snapshot.CreatedAt.Format("2006-01-02 15:04:05 MST")) fmt.Printf("Created At: %s\n", snapshot.CreatedAt.Format("2006-01-02 15:04:05 MST"))
fmt.Printf("Description: %s\n", snapshot.Description) fmt.Printf("Description: %s\n", snapshot.Description)
fmt.Printf("Number of packages: %d\n", snapshot.NumPackages()) fmt.Printf("Number of packages: %d\n", snapshot.NumPackages())
if len(snapshot.SourceIDs) > 0 {
fmt.Printf("Sources:\n")
for _, sourceID := range snapshot.SourceIDs {
var name string
if snapshot.SourceKind == "snapshot" {
source, err := context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
if err != nil {
continue
}
name = source.Name
} else if snapshot.SourceKind == "local" {
source, err := context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
if err != nil {
continue
}
name = source.Name
} else if snapshot.SourceKind == "repo" {
source, err := context.CollectionFactory().RemoteRepoCollection().ByUUID(sourceID)
if err != nil {
continue
}
name = source.Name
}
if name != "" {
fmt.Printf(" %s [%s]\n", name, snapshot.SourceKind)
}
}
}
withPackages := context.Flags().Lookup("with-packages").Value.Get().(bool) withPackages := context.Flags().Lookup("with-packages").Value.Get().(bool)
if withPackages { if withPackages {
+2 -1
View File
@@ -2,9 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"sort"
) )
func aptlySnapshotVerify(cmd *commander.Command, args []string) error { func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
+1 -1
View File
@@ -20,7 +20,7 @@ func aptlyTaskRun(cmd *commander.Command, args []string) error {
var finfo os.FileInfo var finfo os.FileInfo
if finfo, err = os.Stat(filename); os.IsNotExist(err) || finfo.IsDir() { if finfo, err = os.Stat(filename); os.IsNotExist(err) || finfo.IsDir() {
return fmt.Errorf("no such file, %s\n", filename) return fmt.Errorf("no such file, %s", filename)
} }
fmt.Print("Reading file...\n\n") fmt.Print("Reading file...\n\n")
+1
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/commander" "github.com/smira/commander"
) )
+2 -1
View File
@@ -2,10 +2,11 @@ package console
import ( import (
"fmt" "fmt"
"strings"
"github.com/cheggaaa/pb" "github.com/cheggaaa/pb"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/wsxiaoys/terminal/color" "github.com/wsxiaoys/terminal/color"
"strings"
) )
const ( const (
+2 -1
View File
@@ -1,8 +1,9 @@
package console package console
import ( import (
"golang.org/x/crypto/ssh/terminal"
"syscall" "syscall"
"golang.org/x/crypto/ssh/terminal"
) )
// RunningOnTerminal checks whether stdout is terminal // RunningOnTerminal checks whether stdout is terminal
+9 -8
View File
@@ -3,6 +3,14 @@ package context
import ( import (
"fmt" "fmt"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"strings"
"sync"
"time"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/console" "github.com/smira/aptly/console"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
@@ -14,13 +22,6 @@ import (
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"strings"
"sync"
"time"
) )
// AptlyContext is a common context shared by all commands // AptlyContext is a common context shared by all commands
@@ -337,7 +338,7 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto
var err error var err error
publishedStorage, err = swift.NewPublishedStorage(params.UserName, params.Password, publishedStorage, err = swift.NewPublishedStorage(params.UserName, params.Password,
params.AuthURL, params.Tenant, params.TenantID, params.Container, params.Prefix) params.AuthURL, params.Tenant, params.TenantID, params.Domain, params.DomainID, params.TenantDomain, params.TenantDomainID, params.Container, params.Prefix)
if err != nil { if err != nil {
Fatal(err) Fatal(err)
} }
+65 -3
View File
@@ -4,6 +4,9 @@ package database
import ( import (
"bytes" "bytes"
"errors" "errors"
"io/ioutil"
"os"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/opt" "github.com/syndtr/goleveldb/leveldb/opt"
@@ -16,11 +19,17 @@ var (
ErrNotFound = errors.New("key not found") ErrNotFound = errors.New("key not found")
) )
// StorageProcessor is a function to process one single storage entry
type StorageProcessor func(key []byte, value []byte) error
// Storage is an interface to KV storage // Storage is an interface to KV storage
type Storage interface { type Storage interface {
CreateTemporary() (Storage, error)
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 Delete(key []byte) error
HasPrefix(prefix []byte) bool
ProcessByPrefix(prefix []byte, proc StorageProcessor) error
KeysByPrefix(prefix []byte) [][]byte KeysByPrefix(prefix []byte) [][]byte
FetchByPrefix(prefix []byte) [][]byte FetchByPrefix(prefix []byte) [][]byte
Close() error Close() error
@@ -28,6 +37,7 @@ type Storage interface {
StartBatch() StartBatch()
FinishBatch() error FinishBatch() error
CompactDB() error CompactDB() error
Drop() error
} }
type levelDB struct { type levelDB struct {
@@ -41,18 +51,24 @@ var (
_ Storage = &levelDB{} _ Storage = &levelDB{}
) )
func internalOpen(path string) (*leveldb.DB, error) { func internalOpen(path string, throttleCompaction bool) (*leveldb.DB, error) {
o := &opt.Options{ o := &opt.Options{
Filter: filter.NewBloomFilter(10), Filter: filter.NewBloomFilter(10),
OpenFilesCacheCapacity: 256, OpenFilesCacheCapacity: 256,
} }
if throttleCompaction {
o.CompactionL0Trigger = 32
o.WriteL0PauseTrigger = 96
o.WriteL0SlowdownTrigger = 64
}
return leveldb.OpenFile(path, o) return leveldb.OpenFile(path, o)
} }
// OpenDB opens (creates) LevelDB database // OpenDB opens (creates) LevelDB database
func OpenDB(path string) (Storage, error) { func OpenDB(path string) (Storage, error) {
db, err := internalOpen(path) db, err := internalOpen(path, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -77,6 +93,20 @@ func RecoverDB(path string) error {
return nil return nil
} }
// CreateTemporary creates new DB of the same type in temp dir
func (l *levelDB) CreateTemporary() (Storage, error) {
tempdir, err := ioutil.TempDir("", "aptly")
if err != nil {
return nil, err
}
db, err := internalOpen(tempdir, true)
if err != nil {
return nil, err
}
return &levelDB{db: db, path: tempdir}, nil
}
// Get key value from database // Get key value from database
func (l *levelDB) Get(key []byte) ([]byte, error) { func (l *levelDB) Get(key []byte) ([]byte, error) {
value, err := l.db.Get(key, nil) value, err := l.db.Get(key, nil)
@@ -152,6 +182,29 @@ func (l *levelDB) FetchByPrefix(prefix []byte) [][]byte {
return result return result
} }
// HasPrefix checks whether it can find any key with given prefix and returns true if one exists
func (l *levelDB) HasPrefix(prefix []byte) bool {
iterator := l.db.NewIterator(nil, nil)
defer iterator.Release()
return iterator.Seek(prefix) && bytes.HasPrefix(iterator.Key(), prefix)
}
// ProcessByPrefix iterates through all entries where key starts with prefix and calls
// StorageProcessor on key value pair
func (l *levelDB) ProcessByPrefix(prefix []byte, proc StorageProcessor) error {
iterator := l.db.NewIterator(nil, nil)
defer iterator.Release()
for ok := iterator.Seek(prefix); ok && bytes.HasPrefix(iterator.Key(), prefix); ok = iterator.Next() {
err := proc(iterator.Key(), iterator.Value())
if err != nil {
return err
}
}
return nil
}
// Close finishes DB work // Close finishes DB work
func (l *levelDB) Close() error { func (l *levelDB) Close() error {
if l.db == nil { if l.db == nil {
@@ -169,7 +222,7 @@ func (l *levelDB) ReOpen() error {
} }
var err error var err error
l.db, err = internalOpen(l.path) l.db, err = internalOpen(l.path, false)
return err return err
} }
@@ -197,3 +250,12 @@ func (l *levelDB) FinishBatch() error {
func (l *levelDB) CompactDB() error { func (l *levelDB) CompactDB() error {
return l.db.CompactRange(util.Range{}) return l.db.CompactRange(util.Range{})
} }
// Drop removes all the DB files (DANGEROUS!)
func (l *levelDB) Drop() error {
if l.db != nil {
return errors.New("DB is still open")
}
return os.RemoveAll(l.path)
}
+54
View File
@@ -71,6 +71,29 @@ func (s *LevelDBSuite) TestGetPut(c *C) {
c.Assert(result, DeepEquals, value) c.Assert(result, DeepEquals, value)
} }
func (s *LevelDBSuite) TestTemporaryDelete(c *C) {
var (
key = []byte("key")
value = []byte("value")
)
err := s.db.Put(key, value)
c.Assert(err, IsNil)
temp, err := s.db.CreateTemporary()
c.Assert(err, IsNil)
c.Check(s.db.HasPrefix([]byte(nil)), Equals, true)
c.Check(temp.HasPrefix([]byte(nil)), Equals, false)
err = temp.Put(key, value)
c.Assert(err, IsNil)
c.Check(temp.HasPrefix([]byte(nil)), Equals, true)
c.Assert(temp.Close(), IsNil)
c.Assert(temp.Drop(), IsNil)
}
func (s *LevelDBSuite) TestDelete(c *C) { func (s *LevelDBSuite) TestDelete(c *C) {
var ( var (
key = []byte("key") key = []byte("key")
@@ -107,10 +130,41 @@ func (s *LevelDBSuite) TestByPrefix(c *C) {
c.Check(s.db.FetchByPrefix([]byte{0x80}), DeepEquals, [][]byte{{0x01}, {0x02}, {0x03}}) c.Check(s.db.FetchByPrefix([]byte{0x80}), DeepEquals, [][]byte{{0x01}, {0x02}, {0x03}})
c.Check(s.db.KeysByPrefix([]byte{0x80}), DeepEquals, [][]byte{{0x80, 0x01}, {0x80, 0x02}, {0x80, 0x03}}) c.Check(s.db.KeysByPrefix([]byte{0x80}), DeepEquals, [][]byte{{0x80, 0x01}, {0x80, 0x02}, {0x80, 0x03}})
keys := [][]byte{}
values := [][]byte{}
c.Check(s.db.ProcessByPrefix([]byte{0x80}, func(k, v []byte) error {
keys = append(keys, append([]byte(nil), k...))
values = append(values, append([]byte(nil), v...))
return nil
}), IsNil)
c.Check(values, DeepEquals, [][]byte{{0x01}, {0x02}, {0x03}})
c.Check(keys, DeepEquals, [][]byte{{0x80, 0x01}, {0x80, 0x02}, {0x80, 0x03}})
c.Check(s.db.ProcessByPrefix([]byte{0x80}, func(k, v []byte) error {
return ErrNotFound
}), Equals, ErrNotFound)
c.Check(s.db.ProcessByPrefix([]byte{0xa0}, func(k, v []byte) error {
return ErrNotFound
}), IsNil)
c.Check(s.db.FetchByPrefix([]byte{0xa0}), DeepEquals, [][]byte{}) c.Check(s.db.FetchByPrefix([]byte{0xa0}), DeepEquals, [][]byte{})
c.Check(s.db.KeysByPrefix([]byte{0xa0}), DeepEquals, [][]byte{}) c.Check(s.db.KeysByPrefix([]byte{0xa0}), DeepEquals, [][]byte{})
} }
func (s *LevelDBSuite) TestHasPrefix(c *C) {
c.Check(s.db.HasPrefix([]byte(nil)), Equals, false)
c.Check(s.db.HasPrefix([]byte{0x80}), Equals, false)
s.db.Put([]byte{0x80, 0x01}, []byte{0x01})
c.Check(s.db.HasPrefix([]byte(nil)), Equals, true)
c.Check(s.db.HasPrefix([]byte{0x80}), Equals, true)
c.Check(s.db.HasPrefix([]byte{0x79}), Equals, false)
}
func (s *LevelDBSuite) TestBatch(c *C) { func (s *LevelDBSuite) TestBatch(c *C) {
var ( var (
key = []byte("key") key = []byte("key")
+21 -2
View File
@@ -2,13 +2,14 @@ package deb
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
) )
// Changes is a result of .changes file parsing // Changes is a result of .changes file parsing
@@ -179,11 +180,29 @@ func (c *Changes) PackageQuery() (PackageQuery, error) {
var binaryQuery PackageQuery var binaryQuery PackageQuery
if len(c.Binary) > 0 { if len(c.Binary) > 0 {
binaryQuery = &FieldQuery{Field: "Name", Relation: VersionEqual, Value: c.Binary[0]} binaryQuery = &FieldQuery{Field: "Name", Relation: VersionEqual, Value: c.Binary[0]}
// matching debug ddeb packages, they're not present in the Binary field
var ddebQuery PackageQuery
ddebQuery = &FieldQuery{Field: "Name", Relation: VersionEqual, Value: fmt.Sprintf("%s-dbgsym", c.Binary[0])}
for _, binary := range c.Binary[1:] { for _, binary := range c.Binary[1:] {
binaryQuery = &OrQuery{ binaryQuery = &OrQuery{
L: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: binary}, L: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: binary},
R: binaryQuery, R: binaryQuery,
} }
ddebQuery = &OrQuery{
L: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: fmt.Sprintf("%s-dbgsym", binary)},
R: ddebQuery,
}
}
ddebQuery = &AndQuery{
L: &FieldQuery{Field: "Source", Relation: VersionEqual, Value: c.Source},
R: ddebQuery,
}
binaryQuery = &OrQuery{
L: binaryQuery,
R: ddebQuery,
} }
binaryQuery = &AndQuery{ binaryQuery = &AndQuery{
+3 -2
View File
@@ -1,9 +1,10 @@
package deb package deb
import ( import (
. "gopkg.in/check.v1"
"os" "os"
"path/filepath" "path/filepath"
. "gopkg.in/check.v1"
) )
type ChangesSuite struct { type ChangesSuite struct {
@@ -54,7 +55,7 @@ func (s *ChangesSuite) TestPackageQuery(c *C) {
c.Check(err, IsNil) c.Check(err, IsNil)
c.Check(q.String(), Equals, c.Check(q.String(), Equals,
"(($Architecture (= amd64)) | (($Architecture (= source)) | ($Architecture (= )))), ((($PackageType (= source)), (Name (= calamares))) | ((!($PackageType (= source))), ((Name (= calamares-dbg)) | (Name (= calamares)))))") "(($Architecture (= amd64)) | (($Architecture (= source)) | ($Architecture (= )))), ((($PackageType (= source)), (Name (= calamares))) | ((!($PackageType (= source))), (((Name (= calamares-dbg)) | (Name (= calamares))) | ((Source (= calamares)), ((Name (= calamares-dbg-dbgsym)) | (Name (= calamares-dbgsym)))))))")
} }
var changesFile = `Format: 1.8 var changesFile = `Format: 1.8
+9 -1
View File
@@ -1,8 +1,9 @@
package deb package deb
import ( import (
"github.com/smira/aptly/database"
"sync" "sync"
"github.com/smira/aptly/database"
) )
// CollectionFactory is a single place to generate all desired collections // CollectionFactory is a single place to generate all desired collections
@@ -21,6 +22,13 @@ func NewCollectionFactory(db database.Storage) *CollectionFactory {
return &CollectionFactory{Mutex: &sync.Mutex{}, db: db} return &CollectionFactory{Mutex: &sync.Mutex{}, db: db}
} }
// TemporaryDB creates new temporary DB
//
// DB should be closed/droped after being used
func (factory *CollectionFactory) TemporaryDB() (database.Storage, error) {
return factory.db.CreateTemporary()
}
// PackageCollection returns (or creates) new PackageCollection // PackageCollection returns (or creates) new PackageCollection
func (factory *CollectionFactory) PackageCollection() *PackageCollection { func (factory *CollectionFactory) PackageCollection() *PackageCollection {
factory.Lock() factory.Lock()
+90 -30
View File
@@ -1,75 +1,135 @@
package deb package deb
import ( import (
"bytes"
"errors"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"io" "io"
"sort"
"strings" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/database"
"github.com/smira/go-uuid/uuid"
) )
// ContentsIndex calculates mapping from files to packages, with sorting and aggregation // ContentsIndex calculates mapping from files to packages, with sorting and aggregation
type ContentsIndex struct { type ContentsIndex struct {
index map[string][]*Package db database.Storage
prefix []byte
} }
// NewContentsIndex creates empty ContentsIndex // NewContentsIndex creates empty ContentsIndex
func NewContentsIndex() *ContentsIndex { func NewContentsIndex(db database.Storage) *ContentsIndex {
return &ContentsIndex{ return &ContentsIndex{
index: make(map[string][]*Package), db: db,
prefix: []byte(uuid.New()),
} }
} }
// Push adds package to contents index, calculating package contents as required // Push adds package to contents index, calculating package contents as required
func (index *ContentsIndex) Push(p *Package, packagePool aptly.PackagePool) { func (index *ContentsIndex) Push(p *Package, packagePool aptly.PackagePool) error {
contents := p.Contents(packagePool) contents := p.Contents(packagePool)
qualifiedName := []byte(p.QualifiedName())
for _, path := range contents { for _, path := range contents {
index.index[path] = append(index.index[path], p) // for performance reasons we only write to leveldb during push.
// merging of qualified names per path will be done in WriteTo
err := index.db.Put(append(append(append(index.prefix, []byte(path)...), byte(0)), qualifiedName...), nil)
if err != nil {
return err
}
} }
return nil
} }
// Empty checks whether index contains no packages // Empty checks whether index contains no packages
func (index *ContentsIndex) Empty() bool { func (index *ContentsIndex) Empty() bool {
return len(index.index) == 0 return !index.db.HasPrefix(index.prefix)
} }
// WriteTo dumps sorted mapping of files to qualified package names // WriteTo dumps sorted mapping of files to qualified package names
func (index *ContentsIndex) WriteTo(w io.Writer) (int64, error) { func (index *ContentsIndex) WriteTo(w io.Writer) (int64, error) {
// For performance reasons push method wrote on key per path and package
// in this method we now need to merge all packages which have the same path
// and write it to contents index file
var n int64 var n int64
paths := make([]string, len(index.index))
i := 0
for path := range index.index {
paths[i] = path
i++
}
sort.Strings(paths)
nn, err := fmt.Fprintf(w, "%s %s\n", "FILE", "LOCATION") nn, err := fmt.Fprintf(w, "%s %s\n", "FILE", "LOCATION")
n += int64(nn) n += int64(nn)
if err != nil { if err != nil {
return n, err return n, err
} }
for _, path := range paths { prefixLen := len(index.prefix)
packages := index.index[path]
parts := make([]string, 0, len(packages)) var (
for i := range packages { currentPath []byte
name := packages[i].QualifiedName() currentPkgs [][]byte
if !utils.StrSliceHasItem(parts, name) { )
parts = append(parts, name)
} err = index.db.ProcessByPrefix(index.prefix, func(key []byte, value []byte) error {
// cut prefix
key = key[prefixLen:]
i := bytes.Index(key, []byte{0})
if i == -1 {
return errors.New("corrupted index entry")
} }
nn, err = fmt.Fprintf(w, "%s %s\n", path, strings.Join(parts, ","))
path := key[:i]
pkg := key[i+1:]
if !bytes.Equal(path, currentPath) {
if currentPath != nil {
nn, err = w.Write(append(currentPath, ' '))
n += int64(nn)
if err != nil {
return err
}
nn, err = w.Write(bytes.Join(currentPkgs, []byte{','}))
n += int64(nn)
if err != nil {
return err
}
nn, err = w.Write([]byte{'\n'})
n += int64(nn)
if err != nil {
return err
}
}
currentPath = append([]byte(nil), path...)
currentPkgs = nil
}
currentPkgs = append(currentPkgs, append([]byte(nil), pkg...))
return nil
})
if err != nil {
return n, err
}
if currentPath != nil {
nn, err = w.Write(append(currentPath, ' '))
n += int64(nn) n += int64(nn)
if err != nil { if err != nil {
return n, err return n, err
} }
nn, err = w.Write(bytes.Join(currentPkgs, []byte{','}))
n += int64(nn)
if err != nil {
return n, err
}
nn, err = w.Write([]byte{'\n'})
n += int64(nn)
} }
return n, nil return n, err
} }
+29 -13
View File
@@ -2,16 +2,20 @@ package deb
import ( import (
"archive/tar" "archive/tar"
"bufio"
"compress/bzip2" "compress/bzip2"
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"github.com/mkrautz/goar"
"github.com/smira/aptly/utils"
"github.com/smira/go-xz"
"github.com/smira/lzma"
"io" "io"
"os" "os"
"strings" "strings"
"github.com/h2non/filetype/matchers"
"github.com/mkrautz/goar"
"github.com/smira/aptly/utils"
"github.com/smira/go-xz"
"github.com/smira/lzma"
) )
// GetControlFileFromDeb reads control file from deb package // GetControlFileFromDeb reads control file from deb package
@@ -119,29 +123,41 @@ func GetContentsFromDeb(packageFile string) ([]string, error) {
} }
if strings.HasPrefix(header.Name, "data.tar") { if strings.HasPrefix(header.Name, "data.tar") {
bufReader := bufio.NewReader(library)
signature, err := bufReader.Peek(270)
var isTar bool
if err == nil {
isTar = matchers.Tar(signature)
}
var tarInput io.Reader var tarInput io.Reader
switch header.Name { switch header.Name {
case "data.tar": case "data.tar":
tarInput = library tarInput = bufReader
case "data.tar.gz": case "data.tar.gz":
ungzip, err := gzip.NewReader(library) if isTar {
if err != nil { tarInput = bufReader
return nil, fmt.Errorf("unable to ungzip data.tar.gz from %s: %s", packageFile, err) } else {
ungzip, err := gzip.NewReader(bufReader)
if err != nil {
return nil, fmt.Errorf("unable to ungzip data.tar.gz from %s: %s", packageFile, err)
}
defer ungzip.Close()
tarInput = ungzip
} }
defer ungzip.Close()
tarInput = ungzip
case "data.tar.bz2": case "data.tar.bz2":
tarInput = bzip2.NewReader(library) tarInput = bzip2.NewReader(bufReader)
case "data.tar.xz": case "data.tar.xz":
unxz, err := xz.NewReader(library) unxz, err := xz.NewReader(bufReader)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to unxz data.tar.xz from %s: %s", packageFile, err) return nil, fmt.Errorf("unable to unxz data.tar.xz from %s: %s", packageFile, err)
} }
defer unxz.Close() defer unxz.Close()
tarInput = unxz tarInput = unxz
case "data.tar.lzma": case "data.tar.lzma":
unlzma := lzma.NewReader(library) unlzma := lzma.NewReader(bufReader)
defer unlzma.Close() defer unlzma.Close()
tarInput = unlzma tarInput = unlzma
default: default:
+2 -1
View File
@@ -1,10 +1,11 @@
package deb package deb
import ( import (
"github.com/smira/aptly/utils"
"path/filepath" "path/filepath"
"runtime" "runtime"
"github.com/smira/aptly/utils"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
+28 -10
View File
@@ -2,18 +2,34 @@ package deb
import ( import (
"fmt" "fmt"
"github.com/awalterschulze/gographviz"
"strings" "strings"
"github.com/awalterschulze/gographviz"
) )
// BuildGraph generates graph contents from aptly object database // BuildGraph generates graph contents from aptly object database
func BuildGraph(collectionFactory *CollectionFactory) (gographviz.Interface, error) { func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz.Interface, error) {
var err error var err error
graph := gographviz.NewEscape() graph := gographviz.NewEscape()
graph.SetDir(true) graph.SetDir(true)
graph.SetName("aptly") graph.SetName("aptly")
var labelStart string
var labelEnd string
switch layout {
case "vertical":
graph.AddAttr("aptly", "rankdir", "LR")
labelStart = ""
labelEnd = ""
case "horizontal":
fallthrough
default:
labelStart = "{"
labelEnd = "}"
}
existingNodes := map[string]bool{} existingNodes := map[string]bool{}
err = collectionFactory.RemoteRepoCollection().ForEach(func(repo *RemoteRepo) error { err = collectionFactory.RemoteRepoCollection().ForEach(func(repo *RemoteRepo) error {
@@ -26,9 +42,9 @@ func BuildGraph(collectionFactory *CollectionFactory) (gographviz.Interface, err
"shape": "Mrecord", "shape": "Mrecord",
"style": "filled", "style": "filled",
"fillcolor": "darkgoldenrod1", "fillcolor": "darkgoldenrod1",
"label": fmt.Sprintf("{Mirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d}", "label": fmt.Sprintf("%sMirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d%s", labelStart, repo.Name, repo.ArchiveRoot,
repo.Name, repo.ArchiveRoot, repo.Distribution, strings.Join(repo.Components, ", "), repo.Distribution, strings.Join(repo.Components, ", "),
strings.Join(repo.Architectures, ", "), repo.NumPackages()), strings.Join(repo.Architectures, ", "), repo.NumPackages(), labelEnd),
}) })
existingNodes[repo.UUID] = true existingNodes[repo.UUID] = true
return nil return nil
@@ -48,8 +64,8 @@ func BuildGraph(collectionFactory *CollectionFactory) (gographviz.Interface, err
"shape": "Mrecord", "shape": "Mrecord",
"style": "filled", "style": "filled",
"fillcolor": "mediumseagreen", "fillcolor": "mediumseagreen",
"label": fmt.Sprintf("{Repo %s|comment: %s|pkgs: %d}", "label": fmt.Sprintf("%sRepo %s|comment: %s|pkgs: %d%s", labelStart,
repo.Name, repo.Comment, repo.NumPackages()), repo.Name, repo.Comment, repo.NumPackages(), labelEnd),
}) })
existingNodes[repo.UUID] = true existingNodes[repo.UUID] = true
return nil return nil
@@ -79,7 +95,8 @@ func BuildGraph(collectionFactory *CollectionFactory) (gographviz.Interface, err
"shape": "Mrecord", "shape": "Mrecord",
"style": "filled", "style": "filled",
"fillcolor": "cadetblue1", "fillcolor": "cadetblue1",
"label": fmt.Sprintf("{Snapshot %s|%s|pkgs: %d}", snapshot.Name, description, snapshot.NumPackages()), "label": fmt.Sprintf("%sSnapshot %s|%s|pkgs: %d%s", labelStart,
snapshot.Name, description, snapshot.NumPackages(), labelEnd),
}) })
if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" { if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" {
@@ -102,8 +119,9 @@ func BuildGraph(collectionFactory *CollectionFactory) (gographviz.Interface, err
"shape": "Mrecord", "shape": "Mrecord",
"style": "filled", "style": "filled",
"fillcolor": "darkolivegreen1", "fillcolor": "darkolivegreen1",
"label": fmt.Sprintf("{Published %s/%s|comp: %s|arch: %s}", repo.Prefix, repo.Distribution, "label": fmt.Sprintf("%sPublished %s/%s|comp: %s|arch: %s%s", labelStart,
strings.Join(repo.Components(), " "), strings.Join(repo.Architectures, ", ")), repo.Prefix, repo.Distribution, strings.Join(repo.Components(), " "),
strings.Join(repo.Architectures, ", "), labelEnd),
}) })
for _, uuid := range repo.Sources { for _, uuid := range repo.Sources {
+3 -2
View File
@@ -1,12 +1,13 @@
package deb package deb
import ( import (
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
) )
// CollectPackageFiles walks filesystem collecting all candidates for package files // CollectPackageFiles walks filesystem collecting all candidates for package files
+4 -3
View File
@@ -3,11 +3,12 @@ package deb
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
) )
type indexFiles struct { type indexFiles struct {
@@ -62,7 +63,7 @@ func (file *indexFile) Finalize(signer utils.Signer) error {
} }
if file.compressable { if file.compressable {
err = utils.CompressFile(file.tempFile) err = utils.CompressFile(file.tempFile, file.onlyGzip)
if err != nil { if err != nil {
file.tempFile.Close() file.tempFile.Close()
return fmt.Errorf("unable to compress index file: %s", err) return fmt.Errorf("unable to compress index file: %s", err)
+4 -2
View File
@@ -2,9 +2,10 @@ package deb
import ( import (
"fmt" "fmt"
"sort"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"sort"
) )
// Dependency options // Dependency options
@@ -66,6 +67,7 @@ func NewPackageList() *PackageList {
return NewPackageListWithDuplicates(false, 1000) return NewPackageListWithDuplicates(false, 1000)
} }
// NewPackageListWithDuplicates creates empty package list which might allow or block duplicate packages
func NewPackageListWithDuplicates(duplicates bool, capacity int) *PackageList { func NewPackageListWithDuplicates(duplicates bool, capacity int) *PackageList {
if capacity == 0 { if capacity == 0 {
capacity = 1000 capacity = 1000
@@ -247,7 +249,7 @@ func (l *PackageList) Strings() []string {
for _, p := range l.packages { for _, p := range l.packages {
result[i] = string(p.Key("")) result[i] = string(p.Key(""))
i += 1 i++
} }
return result return result
+3 -2
View File
@@ -3,11 +3,12 @@ package deb
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"log"
"sync"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/smira/go-uuid/uuid" "github.com/smira/go-uuid/uuid"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
"log"
"sync"
) )
// LocalRepo is a collection of packages created locally // LocalRepo is a collection of packages created locally
+1
View File
@@ -2,6 +2,7 @@ package deb
import ( import (
"errors" "errors"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
+4 -3
View File
@@ -3,11 +3,12 @@ package deb
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
) )
// Package is single instance of Debian package // Package is single instance of Debian package
@@ -317,7 +318,7 @@ func (p *Package) GetArchitecture() string {
return p.Architecture return p.Architecture
} }
// GetDependencies compiles list of dependenices by flags from options // GetDependencies compiles list of dependncies by flags from options
func (p *Package) GetDependencies(options int) (dependencies []string) { func (p *Package) GetDependencies(options int) (dependencies []string) {
deps := p.Deps() deps := p.Deps()
+2 -1
View File
@@ -3,10 +3,11 @@ package deb
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"path/filepath"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
"path/filepath"
) )
// PackageCollection does management of packages in DB // PackageCollection does management of packages in DB
+3 -3
View File
@@ -64,9 +64,9 @@ func (s *PackageCollectionSuite) TestByKey(c *C) {
c.Check(p2.Files()[0].Filename, Equals, "alien-arena-common_7.40-2_i386.deb") c.Check(p2.Files()[0].Filename, Equals, "alien-arena-common_7.40-2_i386.deb")
} }
func (s *PackageCollectionSuite) TestByKeyOld_0_3(c *C) { func (s *PackageCollectionSuite) TestByKeyOld0_3(c *C) {
key := []byte("Pi386 vmware-view-open-client 4.5.0-297975+dfsg-4+b1") key := []byte("Pi386 vmware-view-open-client 4.5.0-297975+dfsg-4+b1")
s.db.Put(key, old_0_3_Package) s.db.Put(key, old0_3Package)
p, err := s.collection.ByKey(key) p, err := s.collection.ByKey(key)
c.Check(err, IsNil) c.Check(err, IsNil)
@@ -133,7 +133,7 @@ func (s *PackageCollectionSuite) TestDeleteByKey(c *C) {
} }
// This is old package (pre-0.4) that would habe to be converted // This is old package (pre-0.4) that would habe to be converted
var old_0_3_Package = []byte{0x8f, 0xac, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0xa4, 0x69, 0x33, 0x38, 0x36, var old0_3Package = []byte{0x8f, 0xac, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0xa4, 0x69, 0x33, 0x38, 0x36,
0xac, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0xc0, 0xb1, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x65, 0xac, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0xc0, 0xb1, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x65,
0x70, 0x65, 0x6e, 0x64, 0x73, 0x49, 0x6e, 0x44, 0x65, 0x70, 0xc0, 0xa7, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0xdc, 0x0, 0x12, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x49, 0x6e, 0x44, 0x65, 0x70, 0xc0, 0xa7, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0xdc, 0x0, 0x12,
0xb7, 0x6c, 0x69, 0x62, 0x61, 0x74, 0x6b, 0x31, 0x2e, 0x30, 0x2d, 0x30, 0x20, 0x28, 0x3e, 0x3d, 0x20, 0x31, 0x2e, 0x31, 0x32, 0x2e, 0xb7, 0x6c, 0x69, 0x62, 0x61, 0x74, 0x6b, 0x31, 0x2e, 0x30, 0x2d, 0x30, 0x20, 0x28, 0x3e, 0x3d, 0x20, 0x31, 0x2e, 0x31, 0x32, 0x2e,
+3 -2
View File
@@ -3,14 +3,15 @@ package deb
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
"hash/fnv" "hash/fnv"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/utils"
) )
// PackageFile is a single file entry in package // PackageFile is a single file entry in package
+3 -2
View File
@@ -1,11 +1,12 @@
package deb package deb
import ( import (
"github.com/smira/aptly/files"
"github.com/smira/aptly/utils"
"os" "os"
"path/filepath" "path/filepath"
"github.com/smira/aptly/files"
"github.com/smira/aptly/utils"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
+3 -2
View File
@@ -2,12 +2,13 @@ package deb
import ( import (
"bytes" "bytes"
"github.com/smira/aptly/files"
"github.com/smira/aptly/utils"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"github.com/smira/aptly/files"
"github.com/smira/aptly/utils"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
+2 -1
View File
@@ -2,10 +2,11 @@ package deb
import ( import (
"fmt" "fmt"
"github.com/smira/aptly/utils"
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
"github.com/smira/aptly/utils"
) )
var ppaRegexp = regexp.MustCompile("^ppa:([^/]+)/(.+)$") var ppaRegexp = regexp.MustCompile("^ppa:([^/]+)/(.+)$")
+35 -10
View File
@@ -5,11 +5,6 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/database"
"github.com/smira/aptly/utils"
"github.com/smira/go-uuid/uuid"
"github.com/ugorji/go/codec"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
@@ -18,6 +13,13 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/smira/go-uuid/uuid"
"github.com/ugorji/go/codec"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/database"
"github.com/smira/aptly/utils"
) )
type repoSourceItem struct { type repoSourceItem struct {
@@ -49,7 +51,7 @@ type PublishedRepo struct {
// Map of sources by each component: component name -> source UUID // Map of sources by each component: component name -> source UUID
Sources map[string]string Sources map[string]string
// Legacy fields for compatibily with old published repositories (< 0.6) // Legacy fields for compatibility with old published repositories (< 0.6)
Component string Component string
// SourceUUID is UUID of either snapshot or local repo // SourceUUID is UUID of either snapshot or local repo
SourceUUID string `codec:"SnapshotUUID"` SourceUUID string `codec:"SnapshotUUID"`
@@ -467,6 +469,22 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
return err return err
} }
tempDB, err := collectionFactory.TemporaryDB()
if err != nil {
return err
}
defer func() {
var e error
e = tempDB.Close()
if e != nil && progress != nil {
progress.Printf("failed to close temp DB: %s", err)
}
e = tempDB.Drop()
if e != nil && progress != nil {
progress.Printf("failed to drop temp DB: %s", err)
}
}()
if progress != nil { if progress != nil {
progress.Printf("Loading packages...\n") progress.Printf("Loading packages...\n")
} }
@@ -561,7 +579,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
contentIndex := contentIndexes[key] contentIndex := contentIndexes[key]
if contentIndex == nil { if contentIndex == nil {
contentIndex = NewContentsIndex() contentIndex = NewContentsIndex(tempDB)
contentIndexes[key] = contentIndex contentIndexes[key] = contentIndex
} }
@@ -677,7 +695,14 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
release["Components"] = strings.Join(p.Components(), " ") release["Components"] = strings.Join(p.Components(), " ")
for path, info := range indexes.generatedFiles { sortedPaths := make([]string, 0, len(indexes.generatedFiles))
for path := range indexes.generatedFiles {
sortedPaths = append(sortedPaths, path)
}
sort.Strings(sortedPaths)
for _, path := range sortedPaths {
info := indexes.generatedFiles[path]
release["MD5Sum"] += fmt.Sprintf(" %s %8d %s\n", info.MD5, info.Size, path) release["MD5Sum"] += fmt.Sprintf(" %s %8d %s\n", info.MD5, info.Size, path)
release["SHA1"] += fmt.Sprintf(" %s %8d %s\n", info.SHA1, info.Size, path) release["SHA1"] += fmt.Sprintf(" %s %8d %s\n", info.SHA1, info.Size, path)
release["SHA256"] += fmt.Sprintf(" %s %8d %s\n", info.SHA256, info.Size, path) release["SHA256"] += fmt.Sprintf(" %s %8d %s\n", info.SHA256, info.Size, path)
@@ -905,7 +930,7 @@ func (collection *PublishedRepoCollection) ByUUID(uuid string) (*PublishedRepo,
// BySnapshot looks up repository by snapshot source // BySnapshot looks up repository by snapshot source
func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*PublishedRepo { func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*PublishedRepo {
result := make([]*PublishedRepo, 0) var result []*PublishedRepo
for _, r := range collection.list { for _, r := range collection.list {
if r.SourceKind == "snapshot" { if r.SourceKind == "snapshot" {
if r.SourceUUID == snapshot.UUID { if r.SourceUUID == snapshot.UUID {
@@ -925,7 +950,7 @@ func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*Pub
// ByLocalRepo looks up repository by local repo source // ByLocalRepo looks up repository by local repo source
func (collection *PublishedRepoCollection) ByLocalRepo(repo *LocalRepo) []*PublishedRepo { func (collection *PublishedRepoCollection) ByLocalRepo(repo *LocalRepo) []*PublishedRepo {
result := make([]*PublishedRepo, 0) var result []*PublishedRepo
for _, r := range collection.list { for _, r := range collection.list {
if r.SourceKind == "local" { if r.SourceKind == "local" {
if r.SourceUUID == repo.UUID { if r.SourceUUID == repo.UUID {
+4 -3
View File
@@ -4,13 +4,14 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/smira/aptly/files" "github.com/smira/aptly/files"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
"io/ioutil"
"os"
"path/filepath"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
+23
View File
@@ -72,6 +72,9 @@ type DependencyQuery struct {
Dep Dependency Dep Dependency
} }
// MatchAllQuery is query that matches all the packages
type MatchAllQuery struct{}
// Matches if any of L, R matches // Matches if any of L, R matches
func (q *OrQuery) Matches(pkg PackageLike) bool { func (q *OrQuery) Matches(pkg PackageLike) bool {
return q.L.Matches(pkg) || q.R.Matches(pkg) return q.L.Matches(pkg) || q.R.Matches(pkg)
@@ -275,3 +278,23 @@ func (q *PkgQuery) Query(list PackageCatalog) (result *PackageList) {
func (q *PkgQuery) String() string { func (q *PkgQuery) String() string {
return fmt.Sprintf("%s_%s_%s", q.Pkg, q.Version, q.Arch) return fmt.Sprintf("%s_%s_%s", q.Pkg, q.Version, q.Arch)
} }
// Matches on specific properties
func (q *MatchAllQuery) Matches(pkg PackageLike) bool {
return true
}
// Fast is always true for match all query
func (q *MatchAllQuery) Fast(list PackageCatalog) bool {
return true
}
// Query looks up specific package
func (q *MatchAllQuery) Query(list PackageCatalog) (result *PackageList) {
return list.Scan(q)
}
// String interface
func (q *MatchAllQuery) String() string {
return ""
}
+7 -6
View File
@@ -3,9 +3,10 @@ package deb
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"sort"
"github.com/AlekSi/pointer" "github.com/AlekSi/pointer"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
"sort"
) )
// 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
@@ -109,8 +110,8 @@ func (l *PackageRefList) Strings() []string {
return result return result
} }
// Substract returns all packages in l that are not in r // Subtract returns all packages in l that are not in r
func (l *PackageRefList) Substract(r *PackageRefList) *PackageRefList { func (l *PackageRefList) Subtract(r *PackageRefList) *PackageRefList {
result := &PackageRefList{Refs: make([][]byte, 0, 128)} result := &PackageRefList{Refs: make([][]byte, 0, 128)}
// pointer to left and right reflists // pointer to left and right reflists
@@ -270,7 +271,7 @@ func (l *PackageRefList) Diff(r *PackageRefList, packageCollection *PackageColle
// Merge merges reflist r into current reflist. If overrideMatching, merge // Merge merges reflist r into current reflist. If overrideMatching, merge
// replaces matching packages (by architecture/name) with reference from r. // replaces matching packages (by architecture/name) with reference from r.
// If ignoreConflicting is set, all packages are preserved, otherwise conflciting // If ignoreConflicting is set, all packages are preserved, otherwise conflicting
// packages are overwritten with packages from "right" snapshot. // packages are overwritten with packages from "right" snapshot.
func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching, ignoreConflicting bool) (result *PackageRefList) { func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching, ignoreConflicting bool) (result *PackageRefList) {
var overriddenArch, overridenName []byte var overriddenArch, overridenName []byte
@@ -327,7 +328,7 @@ func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching, ignoreConfli
if overrideMatching { if overrideMatching {
if bytes.Equal(archL, overriddenArch) && bytes.Equal(nameL, overridenName) { if bytes.Equal(archL, overriddenArch) && bytes.Equal(nameL, overridenName) {
// this package has already been overriden on the right // this package has already been overridden on the right
il++ il++
continue continue
} }
@@ -389,7 +390,7 @@ func (l *PackageRefList) FilterLatestRefs() {
} }
// Compensate for the reduced set // Compensate for the reduced set
i -= 1 i--
} }
lastArch, lastName, lastVer = arch, name, ver lastArch, lastName, lastVer = arch, name, ver
+7 -6
View File
@@ -2,6 +2,7 @@ package deb
import ( import (
"errors" "errors"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
@@ -156,12 +157,12 @@ func (s *PackageRefListSuite) TestSubstract(c *C) {
l4 := &PackageRefList{Refs: [][]byte{r4, r5}} l4 := &PackageRefList{Refs: [][]byte{r4, r5}}
l5 := &PackageRefList{Refs: [][]byte{r1, r2, r3}} l5 := &PackageRefList{Refs: [][]byte{r1, r2, r3}}
c.Check(l1.Substract(empty), DeepEquals, l1) c.Check(l1.Subtract(empty), DeepEquals, l1)
c.Check(l1.Substract(l2), DeepEquals, l3) c.Check(l1.Subtract(l2), DeepEquals, l3)
c.Check(l1.Substract(l3), DeepEquals, l2) c.Check(l1.Subtract(l3), DeepEquals, l2)
c.Check(l1.Substract(l4), DeepEquals, l5) c.Check(l1.Subtract(l4), DeepEquals, l5)
c.Check(empty.Substract(l1), DeepEquals, empty) c.Check(empty.Subtract(l1), DeepEquals, empty)
c.Check(l2.Substract(l3), DeepEquals, l2) c.Check(l2.Subtract(l3), DeepEquals, l2)
} }
func (s *PackageRefListSuite) TestDiff(c *C) { func (s *PackageRefListSuite) TestDiff(c *C) {
+13 -10
View File
@@ -3,12 +3,6 @@ package deb
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/database"
"github.com/smira/aptly/http"
"github.com/smira/aptly/utils"
"github.com/smira/go-uuid/uuid"
"github.com/ugorji/go/codec"
"log" "log"
"net/url" "net/url"
"os" "os"
@@ -20,6 +14,13 @@ import (
"sync" "sync"
"syscall" "syscall"
"time" "time"
"github.com/smira/aptly/aptly"
"github.com/smira/aptly/database"
"github.com/smira/aptly/http"
"github.com/smira/aptly/utils"
"github.com/smira/go-uuid/uuid"
"github.com/ugorji/go/codec"
) )
// RemoteRepo statuses // RemoteRepo statuses
@@ -60,6 +61,8 @@ type RemoteRepo struct {
FilterWithDeps bool FilterWithDeps bool
// SkipComponentCheck skips component list verification // SkipComponentCheck skips component list verification
SkipComponentCheck bool SkipComponentCheck bool
// SkipArchitectureCheck skips architecture list verification
SkipArchitectureCheck bool
// Status marks state of repository (being updated, no action) // Status marks state of repository (being updated, no action)
Status int Status int
// WorkerPID is PID of the process modifying the mirror (if any) // WorkerPID is PID of the process modifying the mirror (if any)
@@ -316,9 +319,9 @@ ok:
architectures = utils.StrSlicesSubstract(architectures, []string{"source"}) architectures = utils.StrSlicesSubstract(architectures, []string{"source"})
if len(repo.Architectures) == 0 { if len(repo.Architectures) == 0 {
repo.Architectures = architectures repo.Architectures = architectures
} else { } else if !repo.SkipArchitectureCheck {
err = utils.StringsIsSubset(repo.Architectures, architectures, err = utils.StringsIsSubset(repo.Architectures, architectures,
fmt.Sprintf("architecture %%s not available in repo %s", repo)) fmt.Sprintf("architecture %%s not available in repo %s, use -force-architectures to override", repo))
if err != nil { if err != nil {
return err return err
} }
@@ -401,7 +404,7 @@ ok:
// DownloadPackageIndexes downloads & parses package index files // DownloadPackageIndexes downloads & parses package index files
func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.Downloader, collectionFactory *CollectionFactory, func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.Downloader, collectionFactory *CollectionFactory,
ignoreMismatch bool) error { ignoreMismatch bool, maxTries int) error {
if repo.packageList != nil { if repo.packageList != nil {
panic("packageList != nil") panic("packageList != nil")
} }
@@ -431,7 +434,7 @@ func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.
for _, info := range packagesURLs { for _, info := range packagesURLs {
url, kind := info[0], info[1] url, kind := info[0], info[1]
packagesReader, packagesFile, err := http.DownloadTryCompression(d, url, repo.ReleaseFiles, ignoreMismatch) packagesReader, packagesFile, err := http.DownloadTryCompression(d, url, repo.ReleaseFiles, ignoreMismatch, maxTries)
if err != nil { if err != nil {
return err return err
} }
+26 -22
View File
@@ -2,16 +2,17 @@ package deb
import ( import (
"errors" "errors"
"io"
"io/ioutil"
"os"
"sort"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/console" "github.com/smira/aptly/console"
"github.com/smira/aptly/database" "github.com/smira/aptly/database"
"github.com/smira/aptly/files" "github.com/smira/aptly/files"
"github.com/smira/aptly/http" "github.com/smira/aptly/http"
"github.com/smira/aptly/utils" "github.com/smira/aptly/utils"
"io"
"io/ioutil"
"os"
"sort"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
@@ -103,7 +104,7 @@ func (s *RemoteRepoSuite) TearDownTest(c *C) {
func (s *RemoteRepoSuite) TestInvalidURL(c *C) { func (s *RemoteRepoSuite) TestInvalidURL(c *C) {
_, err := NewRemoteRepo("s", "http://lolo%2", "squeeze", []string{"main"}, []string{}, false, false) _, err := NewRemoteRepo("s", "http://lolo%2", "squeeze", []string{"main"}, []string{}, false, false)
c.Assert(err, ErrorMatches, ".*(hexadecimal escape|percent-encoded characters) in host.*") c.Assert(err, ErrorMatches, ".*(hexadecimal escape in host|percent-encoded characters in host|invalid URL escape).*")
} }
func (s *RemoteRepoSuite) TestFlatCreation(c *C) { func (s *RemoteRepoSuite) TestFlatCreation(c *C) {
@@ -197,7 +198,7 @@ func (s *RemoteRepoSuite) TestFetch(c *C) {
func (s *RemoteRepoSuite) TestFetchNullVerifier1(c *C) { func (s *RemoteRepoSuite) TestFetchNullVerifier1(c *C) {
downloader := http.NewFakeDownloader() downloader := http.NewFakeDownloader()
downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/InRelease", &http.HTTPError{Code: 404}) downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/InRelease", &http.Error{Code: 404})
downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release", exampleReleaseFile) downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release", exampleReleaseFile)
downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release.gpg", "GPG") downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release.gpg", "GPG")
@@ -257,11 +258,11 @@ func (s *RemoteRepoSuite) TestDownload(c *C) {
err := s.repo.Fetch(s.downloader, nil) err := s.repo.Fetch(s.downloader, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.bz2", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.bz2", &http.Error{Code: 404})
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile) s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, s.collectionFactory, false) err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, s.collectionFactory, false, 1)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(s.downloader.Empty(), Equals, true) c.Assert(s.downloader.Empty(), Equals, true)
@@ -286,14 +287,14 @@ func (s *RemoteRepoSuite) TestDownloadWithSources(c *C) {
err := s.repo.Fetch(s.downloader, nil) err := s.repo.Fetch(s.downloader, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.bz2", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.bz2", &http.Error{Code: 404})
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile) s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.bz2", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.bz2", &http.Error{Code: 404})
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.HTTPError{Code: 404}) s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile) s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, s.collectionFactory, false) err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, s.collectionFactory, false, 1)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(s.downloader.Empty(), Equals, true) c.Assert(s.downloader.Empty(), Equals, true)
@@ -327,14 +328,15 @@ func (s *RemoteRepoSuite) TestDownloadWithSources(c *C) {
func (s *RemoteRepoSuite) TestDownloadFlat(c *C) { func (s *RemoteRepoSuite) TestDownloadFlat(c *C) {
downloader := http.NewFakeDownloader() downloader := http.NewFakeDownloader()
downloader.ExpectResponse("http://repos.express42.com/virool/precise/Release", exampleReleaseFile) downloader.ExpectResponse("http://repos.express42.com/virool/precise/Release", exampleReleaseFile)
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.bz2", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.bz2", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.gz", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.gz", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.xz", &http.Error{Code: 404})
downloader.ExpectResponse("http://repos.express42.com/virool/precise/Packages", examplePackagesFile) downloader.ExpectResponse("http://repos.express42.com/virool/precise/Packages", examplePackagesFile)
err := s.flat.Fetch(downloader, nil) err := s.flat.Fetch(downloader, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = s.flat.DownloadPackageIndexes(s.progress, downloader, s.collectionFactory, true) err = s.flat.DownloadPackageIndexes(s.progress, downloader, s.collectionFactory, true, 1)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(downloader.Empty(), Equals, true) c.Assert(downloader.Empty(), Equals, true)
@@ -357,17 +359,19 @@ func (s *RemoteRepoSuite) TestDownloadWithSourcesFlat(c *C) {
downloader := http.NewFakeDownloader() downloader := http.NewFakeDownloader()
downloader.ExpectResponse("http://repos.express42.com/virool/precise/Release", exampleReleaseFile) downloader.ExpectResponse("http://repos.express42.com/virool/precise/Release", exampleReleaseFile)
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.bz2", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.bz2", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.gz", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.gz", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Packages.xz", &http.Error{Code: 404})
downloader.ExpectResponse("http://repos.express42.com/virool/precise/Packages", examplePackagesFile) downloader.ExpectResponse("http://repos.express42.com/virool/precise/Packages", examplePackagesFile)
downloader.ExpectError("http://repos.express42.com/virool/precise/Sources.bz2", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Sources.bz2", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Sources.gz", &http.HTTPError{Code: 404}) downloader.ExpectError("http://repos.express42.com/virool/precise/Sources.gz", &http.Error{Code: 404})
downloader.ExpectError("http://repos.express42.com/virool/precise/Sources.xz", &http.Error{Code: 404})
downloader.ExpectResponse("http://repos.express42.com/virool/precise/Sources", exampleSourcesFile) downloader.ExpectResponse("http://repos.express42.com/virool/precise/Sources", exampleSourcesFile)
err := s.flat.Fetch(downloader, nil) err := s.flat.Fetch(downloader, nil)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = s.flat.DownloadPackageIndexes(s.progress, downloader, s.collectionFactory, true) err = s.flat.DownloadPackageIndexes(s.progress, downloader, s.collectionFactory, true, 1)
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(downloader.Empty(), Equals, true) c.Assert(downloader.Empty(), Equals, true)

Some files were not shown because too many files have changed in this diff Show More