mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-13 06:40:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a6541aac41 |
+2
-3
@@ -22,7 +22,8 @@ _testmain.go
|
|||||||
*.exe
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
coverage.txt
|
coverage.html
|
||||||
|
coverage*.out
|
||||||
|
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
@@ -33,5 +34,3 @@ man/aptly.1.html
|
|||||||
man/aptly.1.ronn
|
man/aptly.1.ronn
|
||||||
|
|
||||||
.goxc.local.json
|
.goxc.local.json
|
||||||
|
|
||||||
system/env/
|
|
||||||
|
|||||||
+4
-4
@@ -10,17 +10,17 @@
|
|||||||
"bintray"
|
"bintray"
|
||||||
],
|
],
|
||||||
"TaskSettings": {
|
"TaskSettings": {
|
||||||
"debs": {
|
"deb": {
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"maintainer": "Andrey Smirnov",
|
"maintainer": "Andrey Smirnov",
|
||||||
"maintainer-email": "me@smira.ru",
|
"maintainerEmail": "me@smira.ru",
|
||||||
"description": "Debian repository management tool"
|
"description": "Debian repository management tool"
|
||||||
},
|
},
|
||||||
"metadata-deb": {
|
"metadata-deb": {
|
||||||
"License": "MIT",
|
"License": "MIT",
|
||||||
"Homepage": "https://www.aptly.info/",
|
"Homepage": "https://www.aptly.info/",
|
||||||
"Depends": "bzip2, xz-utils, gnupg, gpgv",
|
"Recommends": "bzip2, graphviz, xz-utils",
|
||||||
"Suggests": "graphviz"
|
"Depends": ""
|
||||||
},
|
},
|
||||||
"other-mapped-files": {
|
"other-mapped-files": {
|
||||||
"/": "root/"
|
"/": "root/"
|
||||||
|
|||||||
+19
-28
@@ -1,9 +1,12 @@
|
|||||||
dist: trusty
|
sudo: false
|
||||||
sudo: required
|
|
||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go_import_path: github.com/aptly-dev/aptly
|
go:
|
||||||
|
- 1.6
|
||||||
|
- 1.7
|
||||||
|
- 1.8
|
||||||
|
- tip
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -13,39 +16,27 @@ addons:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: "EcCzJsqQ3HnIkprBPS1YHErsETcb7KQFBYEzVDE7RYDApWeapLq+r/twMtWMd/fkGeLzr3kWSg7nhSadeHMLYeMl9j+U7ncC5CWG5NMBOj/jowlb9cMCCDlmzMoZLAgR6jm1cJyrWCLsWVlv+D0ZiB0fx4xaBZP/gIr9g6nEwC8="
|
- secure: "YSwtFrMqh4oUvdSQTXBXMHHLWeQgyNEL23ChIZwU0nuDGIcQZ65kipu0PzefedtUbK4ieC065YCUi4UDDh6gPotB/Wu1pnYg3dyQ7rFvhaVYAAUEpajAdXZhlx+7+J8a4FZMeC/kqiahxoRgLbthF9019ouIqhGB9zHKI6/yZwc="
|
||||||
|
- secure: "V7OjWrfQ8UbktgT036jYQPb/7GJT3Ol9LObDr8FYlzsQ+F1uj2wLac6ePuxcOS4FwWOJinWGM1h+JiFkbxbyFqfRNJ0jj0O2p93QyDojxFVOn1mXqqvV66KFqAWR2Vzkny/gDvj8LTvdB1cgAIm2FNOkQc6E1BFnyWS2sN9ea5E="
|
||||||
- secure: "OxiVNmre2JzUszwPNNilKDgIqtfX2gnRSsVz6nuySB1uO2yQsOQmKWJ9cVYgH2IB5H8eWXKOhexcSE28kz6TPLRuEcU9fnqKY3uEkdwm7rJfz9lf+7C4bJEUdA1OIzJppjnWUiXxD7CEPL1DlnMZM24eDQYqa/4WKACAgkK53gE="
|
- secure: "OxiVNmre2JzUszwPNNilKDgIqtfX2gnRSsVz6nuySB1uO2yQsOQmKWJ9cVYgH2IB5H8eWXKOhexcSE28kz6TPLRuEcU9fnqKY3uEkdwm7rJfz9lf+7C4bJEUdA1OIzJppjnWUiXxD7CEPL1DlnMZM24eDQYqa/4WKACAgkK53gE="
|
||||||
- NO_FTP_ACCESS: "yes"
|
|
||||||
- BOTO_CONFIG: /dev/null
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: master
|
|
||||||
env: RUN_LONG_TESTS=no
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
- go: 1.8.x
|
|
||||||
env: RUN_LONG_TESTS=no
|
|
||||||
- go: 1.9.x
|
|
||||||
env: RUN_LONG_TESTS=yes
|
|
||||||
- go: 1.10.x
|
|
||||||
env: RUN_LONG_TESTS=yes
|
|
||||||
- go: master
|
|
||||||
env: RUN_LONG_TESTS=no
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- virtualenv system/env
|
- virtualenv env
|
||||||
- . system/env/bin/activate
|
- . env/bin/activate
|
||||||
- pip install six packaging appdirs
|
- pip install six packaging appdirs
|
||||||
- pip install -U pip setuptools
|
- pip install -U pip setuptools
|
||||||
- pip install -r system/requirements.txt
|
- 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
|
- make version
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- make prepare
|
- make prepare
|
||||||
|
|
||||||
after_success:
|
script: make travis
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
webhooks:
|
webhooks:
|
||||||
|
|||||||
@@ -26,10 +26,3 @@ List of contributors, in chronological order:
|
|||||||
* Harald Sitter (https://github.com/apachelogger)
|
* Harald Sitter (https://github.com/apachelogger)
|
||||||
* Johannes Layher (https://github.com/jola5)
|
* Johannes Layher (https://github.com/jola5)
|
||||||
* Charles Hsu (https://github.com/charz)
|
* Charles Hsu (https://github.com/charz)
|
||||||
* Clemens Rabe (https://github.com/seeraven)
|
|
||||||
* TJ Merritt (https://github.com/tjmerritt)
|
|
||||||
* Matt Martyn (https://github.com/MMartyn)
|
|
||||||
* Ludovico Cavedon (https://github.com/cavedon)
|
|
||||||
* Petr Jediny (https://github.com/pjediny)
|
|
||||||
* Maximilian Stein (https://github.com/steinymity)
|
|
||||||
* Strajan Sebastian (https://github.com/strajansebastian)
|
|
||||||
|
|||||||
-240
@@ -1,240 +0,0 @@
|
|||||||
# Contributing to aptly
|
|
||||||
|
|
||||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to [aptly](https://github.com/smira/aplty) and related repositories, which are hosted in the [aptly-dev Organization](https://github.com/aptly-dev) on GitHub.
|
|
||||||
These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
|
||||||
|
|
||||||
## What should I know before I get started?
|
|
||||||
|
|
||||||
### Code of Conduct
|
|
||||||
|
|
||||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
|
||||||
By participating, you are expected to uphold this code.
|
|
||||||
Please report unacceptable behavior to [team@aptly.info](mailto:team@aptly.info).
|
|
||||||
|
|
||||||
### List of Repositories
|
|
||||||
|
|
||||||
* [aptly-dev/aptly](https://github.com/aptly-dev/aptly) - aptly source code, functional tests, man page
|
|
||||||
* [apty-dev/aptly-dev.github.io](https://github.com/aptly-dev/aptly-dev.github.io) - aptly website (https://www.aptly.info/)
|
|
||||||
* [aptly-dev/aptly-fixture-db](https://github.com/aptly-dev/aptly-fixture-db) & [aptly-dev/aptly-fixture-pool](https://github.com/aptly-dev/aptly-fixture-pool) provide
|
|
||||||
fixtures for aptly functional tests
|
|
||||||
|
|
||||||
## How Can I Contribute?
|
|
||||||
|
|
||||||
### Reporting Bugs
|
|
||||||
|
|
||||||
1. Please search for similar bug report in [issue tracker](https://github.com/aptly-dev/aptly/issues)
|
|
||||||
2. Please verify that bug is not fixed in latest aptly nightly ([download information](https://www.aptly.info/download/))
|
|
||||||
3. Steps to reproduce increases chances for bug to be fixed quickly. If possible, submit PR with new functional test which fails.
|
|
||||||
4. If bug is reproducible with specific package, please provide link to package file.
|
|
||||||
5. Open issue at [GitHub](https://github.com/aptly-dev/aptly/issues)
|
|
||||||
|
|
||||||
### Suggesting Enhancements
|
|
||||||
|
|
||||||
1. Please search [issue tracker](https://github.com/aptly-dev/aptly/issues) for similar feature requests.
|
|
||||||
2. Describe why enhancement is important to you.
|
|
||||||
3. Include any additional details or implementation details.
|
|
||||||
|
|
||||||
### Improving Documentation
|
|
||||||
|
|
||||||
There are two kinds of documentation:
|
|
||||||
|
|
||||||
* [aptly website](https://www.aptly/info)
|
|
||||||
* aptly `man` page
|
|
||||||
|
|
||||||
Core content is mostly the same, but website contains more information, tutorials, examples.
|
|
||||||
|
|
||||||
If you want to update `man` page, please open PR to [main aptly repo](https://github.com/aptly-dev/aptly),
|
|
||||||
details in [man page](#man-page) section.
|
|
||||||
|
|
||||||
If you want to update website, please follow steps below:
|
|
||||||
|
|
||||||
1. Install [hugo](http://gohugo.io/)
|
|
||||||
2. Fork [website source](https://github.com/aptly-dev/aptly-dev.github.io) and clone it
|
|
||||||
3. Launch hugo in development mode: `hugo -w server`
|
|
||||||
4. Navigate to `http://localhost:1313/`: you should see aptly website
|
|
||||||
5. Update documentation, most of the time editing Markdown is all you need.
|
|
||||||
6. Page in browser should reload automatically as you make changes to source files.
|
|
||||||
|
|
||||||
We're always looking for new contributions to [FAQ](https://www.aptly.info/doc/faq/), [tutorials](https://www.aptly.info/tutorial/),
|
|
||||||
general fixes, clarifications, misspellings, grammar mistakes!
|
|
||||||
|
|
||||||
### Your Fist Code Contribution
|
|
||||||
|
|
||||||
Please follow [next section](#development-setup) on development process. When change is ready, please submit PR
|
|
||||||
following [PR template](.github/PULL_REQUEST_TEMPLATE.md).
|
|
||||||
|
|
||||||
Make sure that purpose of your change is clear, all the tests and checks pass, and all new code is covered with tests
|
|
||||||
if that is possible.
|
|
||||||
|
|
||||||
## Development Setup
|
|
||||||
|
|
||||||
This section describes local setup to start contributing to aptly source.
|
|
||||||
|
|
||||||
### Go & Python
|
|
||||||
|
|
||||||
You would need `Go` (latest version is recommended) and `Python` 2.7.x (3.x is not supported yet).
|
|
||||||
|
|
||||||
If you're new to Go, follow [getting started guide](https://golang.org/doc/install) to install it and perform
|
|
||||||
initial setup. With Go 1.8+, default `$GOPATH` is `$HOME/go`, so rest of this document assumes that.
|
|
||||||
|
|
||||||
Usually `$GOPATH/bin` is appended to your `$PATH` to make it easier to run built binaries, but you might choose
|
|
||||||
to prepend it or to skip this test if you're security conscious.
|
|
||||||
|
|
||||||
### Forking and Cloning
|
|
||||||
|
|
||||||
As Go is using repository path in import paths, it's better to clone aptly repo (not your fork) at default location:
|
|
||||||
|
|
||||||
mkdir -p ~/go/src/github.com/smira
|
|
||||||
cd ~/go/src/github.com/smira
|
|
||||||
git clone git@github.com:aptly-dev/aptly.git
|
|
||||||
cd aptly
|
|
||||||
|
|
||||||
For main repo under your GitHub user and add it as another Git remote:
|
|
||||||
|
|
||||||
git remote add <user> git@github.com:<user>/aptly.git
|
|
||||||
|
|
||||||
That way you can continue to build project as is (you don't need to adjust import paths), but you would need
|
|
||||||
to specify your remote name when pushing branches:
|
|
||||||
|
|
||||||
git push <user> <your-branch>
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
You would need some additional tools and Python virtual environment to run tests and checks, install them with:
|
|
||||||
|
|
||||||
make prepare dev system/env
|
|
||||||
|
|
||||||
This is usually one-time action.
|
|
||||||
|
|
||||||
### Building
|
|
||||||
|
|
||||||
If you want to build aptly binary from your current source tree, run:
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
This would build `aptly` in `$GOPATH/bin`, so depending on your `$PATH`, you should be able to run it immediately with:
|
|
||||||
|
|
||||||
aptly
|
|
||||||
|
|
||||||
Or, if it's not on your path:
|
|
||||||
|
|
||||||
~/go/bin/aptly
|
|
||||||
|
|
||||||
### Unit-tests
|
|
||||||
|
|
||||||
aptly has two kinds of tests: unit-tests and functional (system) tests. Functional tests are preferred way to test any
|
|
||||||
feature, but some features are much easier to test with unit-tests (e.g. algorithms, failure scenarios, ...)
|
|
||||||
|
|
||||||
aptly is using standard Go unit-test infrastructure plus [gocheck](http://labix.org/gocheck). Run the unit-tests with:
|
|
||||||
|
|
||||||
make test
|
|
||||||
|
|
||||||
### Functional Tests
|
|
||||||
|
|
||||||
Functional tests are implemented in Python, and they use custom test runner which is similar to Python unit-test
|
|
||||||
runner. Most of the tests start with clean aptly state, run some aptly commands to prepare environment, and finally
|
|
||||||
run some aptly commands capturing output, exit code, checking any additional files being created and so on. API tests
|
|
||||||
are a bit different, as they re-use same aptly process serving API requests.
|
|
||||||
|
|
||||||
The easiest way to run functional tests is to use `make`:
|
|
||||||
|
|
||||||
make system-test
|
|
||||||
|
|
||||||
This would check all the dependencies and run all the tests. Some tests (S3, Swift) require access credentials to
|
|
||||||
be set up in the environment. For example, it needs AWS credentials to run S3 tests (they would be used to publish to S3).
|
|
||||||
If credentials are missing, tests would be skipped.
|
|
||||||
|
|
||||||
You can also run subset of tests manually:
|
|
||||||
|
|
||||||
system/run.py t04_mirror
|
|
||||||
|
|
||||||
This would run all the mirroring tests under `system/t04_mirror` folder.
|
|
||||||
|
|
||||||
Or you can run tests by test name mask:
|
|
||||||
|
|
||||||
system/run.py UpdateMirror*
|
|
||||||
|
|
||||||
Or, you can run specific test by name:
|
|
||||||
|
|
||||||
system/run.py UpdateMirror7Test
|
|
||||||
|
|
||||||
Test runner can update expected output instead of failing on mismatch (this is especially useful while
|
|
||||||
working on new tests):
|
|
||||||
|
|
||||||
system/run.py --capture <test>
|
|
||||||
|
|
||||||
Output for some tests might contain environment-specific things, e.g. your home directory. In that case
|
|
||||||
you can use `${HOME}` and similar variable expansion in expected output files.
|
|
||||||
|
|
||||||
Some tests depend on fixtures, for example pre-populated GPG trusted keys. There are also test fixtures
|
|
||||||
captured after mirror update which contain pre-build aptly database and pool contents. They're useful if you
|
|
||||||
don't want to waste time in the test on populating aptly database while you need some packages to work with.
|
|
||||||
There are some packages available under `system/files/` directory which are used to build contents of local repos.
|
|
||||||
|
|
||||||
*WARNING*: tests are running under current `$HOME` directory with aptly default settings, so they clear completely
|
|
||||||
`~/.aptly.conf` and `~/.aptly` subdirectory between the runs. So it's not wise to have non-dev aptly being used with
|
|
||||||
this default location. You can run aptly under different user or by using non-default config location with non-default
|
|
||||||
aptly root directory.
|
|
||||||
|
|
||||||
### Style Checks
|
|
||||||
|
|
||||||
Style checks could be run with:
|
|
||||||
|
|
||||||
make check
|
|
||||||
|
|
||||||
aptly is using [gometalinter](https://github.com/alecthomas/gometalinter) to run style checks on Go code. Configuration
|
|
||||||
for the linter could be found in [linter.json](linter.json) file. Running linters might take considerable amount of time
|
|
||||||
unfortunately, but usually warning reported by linters hint at real code issues.
|
|
||||||
|
|
||||||
Python code (system tests) are linted with [flake8 tool](https://pypi.python.org/pypi/flake8).
|
|
||||||
|
|
||||||
### Vendored Code
|
|
||||||
|
|
||||||
aptly is using Go vendoring for all the libraries aptly depends upon. `vendor/` directory is checked into the source
|
|
||||||
repository to avoid any problems if source repositories go away. Go build process will automatically prefer vendored
|
|
||||||
packages over packages in `$GOPATH`.
|
|
||||||
|
|
||||||
If you want to update vendored dependencies or to introduce new dependency, use [dep tool](https://github.com/golang/dep).
|
|
||||||
Usually all you need is `dep ensure` or `dep ensure -update`.
|
|
||||||
|
|
||||||
### man Page
|
|
||||||
|
|
||||||
aptly is using combination of [Go templates](http://godoc.org/text/template) and automatically generated text to build `aptly.1` man page. If either source
|
|
||||||
template [man/aptly.1.ronn.tmpl](man/aptly.1.ronn.tmpl) is changed or any command help is changed, run `make man` to regenerate
|
|
||||||
final rendered man page [man/aptly.1](man/aptly.1). In the end of the build, new man page is displayed for visual
|
|
||||||
verification.
|
|
||||||
|
|
||||||
Man page is built with small helper [\_man/gen.go](man/gen.go) which pulls in template, command-line help from [cmd/](cmd/) folder
|
|
||||||
and runs that through [forked copy](https://github.com/smira/ronn) of [ronn](https://github.com/rtomayko/ronn).
|
|
||||||
|
|
||||||
### Bash and Zsh Completion
|
|
||||||
|
|
||||||
Bash and Zsh completion for aptly reside in the same repo under in [completion.d/aptly](completion.d/aptly) and
|
|
||||||
[completion.d/\_aptly](completion.d/_aptly), respectively. It's all hand-crafted.
|
|
||||||
When new option or command is introduced, bash completion should be updated to reflect that change.
|
|
||||||
|
|
||||||
When aptly package is being built, it automatically pulls bash completion and man page into the package.
|
|
||||||
|
|
||||||
## Design
|
|
||||||
|
|
||||||
This section requires future work.
|
|
||||||
|
|
||||||
*TBD*
|
|
||||||
|
|
||||||
### Database
|
|
||||||
|
|
||||||
### Package Pool
|
|
||||||
|
|
||||||
### Package
|
|
||||||
|
|
||||||
### PackageList, PackageRefList
|
|
||||||
|
|
||||||
### LocalRepo, RemoteRepo, Snapshot
|
|
||||||
|
|
||||||
### PublishedRepository
|
|
||||||
|
|
||||||
### Context
|
|
||||||
|
|
||||||
### Collections, CollectionFactory
|
|
||||||
Generated
-290
@@ -1,290 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/AlekSi/pointer"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "08a25bac605b3fcb6cc27f3917b2c2c87451963d"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/DisposaBoy/JsonConfigReader"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "33a99fdf1d5ee1f79b5077e9c06f955ad356d5f4"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/awalterschulze/gographviz"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"ast",
|
|
||||||
"parser",
|
|
||||||
"scanner",
|
|
||||||
"token"
|
|
||||||
]
|
|
||||||
revision = "761fd5fbb34e4c2c138c280395b65b48e4ff5a53"
|
|
||||||
version = "v1.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/aws/aws-sdk-go"
|
|
||||||
packages = [
|
|
||||||
"aws",
|
|
||||||
"aws/awserr",
|
|
||||||
"aws/awsutil",
|
|
||||||
"aws/client",
|
|
||||||
"aws/client/metadata",
|
|
||||||
"aws/corehandlers",
|
|
||||||
"aws/credentials",
|
|
||||||
"aws/credentials/ec2rolecreds",
|
|
||||||
"aws/credentials/endpointcreds",
|
|
||||||
"aws/credentials/stscreds",
|
|
||||||
"aws/defaults",
|
|
||||||
"aws/ec2metadata",
|
|
||||||
"aws/endpoints",
|
|
||||||
"aws/request",
|
|
||||||
"aws/session",
|
|
||||||
"aws/signer/v4",
|
|
||||||
"internal/sdkio",
|
|
||||||
"internal/sdkrand",
|
|
||||||
"internal/shareddefaults",
|
|
||||||
"private/protocol",
|
|
||||||
"private/protocol/query",
|
|
||||||
"private/protocol/query/queryutil",
|
|
||||||
"private/protocol/rest",
|
|
||||||
"private/protocol/restxml",
|
|
||||||
"private/protocol/xml/xmlutil",
|
|
||||||
"service/s3",
|
|
||||||
"service/sts"
|
|
||||||
]
|
|
||||||
revision = "a72204b9bf8d48230ee0fe8995613b394c66f2da"
|
|
||||||
version = "v1.13.31"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/cheggaaa/pb"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "cdf719fac0dd208251aa828e687c2d5802053b51"
|
|
||||||
version = "v1.0.10"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/gin-contrib/sse"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/gin-gonic/gin"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"binding",
|
|
||||||
"render"
|
|
||||||
]
|
|
||||||
revision = "d459835d2b077e44f7c9b453505ee29881d5d12d"
|
|
||||||
version = "v1.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/go-ini/ini"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "1730955e3146956d6a087861380f9b4667ed5071"
|
|
||||||
version = "v1.26.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/golang/protobuf"
|
|
||||||
packages = ["proto"]
|
|
||||||
revision = "130e6b02ab059e7b717a096f397c5b60111cae74"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/golang/snappy"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "553a641470496b2327abcac10b36396bd98e45c9"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/h2non/filetype"
|
|
||||||
packages = ["matchers"]
|
|
||||||
revision = "cc14fdc9ca0e4c2bafad7458f6ff79fd3947cfbb"
|
|
||||||
version = "v1.0.5"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/jlaffaye/ftp"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "2403248fa8cc9f7909862627aa7337f13f8e0bf1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/jmespath/go-jmespath"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "0b12d6b5"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/mattn/go-isatty"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
|
||||||
version = "v0.0.3"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/mattn/go-runewidth"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
|
|
||||||
version = "v0.0.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/mattn/go-shellwords"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "005a0944d84452842197c2108bd9168ced206f78"
|
|
||||||
version = "v1.0.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/mkrautz/goar"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "282caa8bd9daba480b51f1d5a988714913b97aad"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/mxk/go-flowrate"
|
|
||||||
packages = ["flowrate"]
|
|
||||||
revision = "cca7078d478f8520f85629ad7c68962d31ed7682"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/ncw/swift"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"swifttest"
|
|
||||||
]
|
|
||||||
revision = "8e9b10220613abdbc2896808ee6b43e411a4fa6c"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/pkg/errors"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
|
||||||
version = "v0.8.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/commander"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "f408b00e68d5d6e21b9f18bd310978dafc604e47"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/flag"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "695ea5e84e76dea7c8656e43c384e54b32aa1b2a"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-aws-auth"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "0070896e9d7f4f9f2d558532b2d896ce2239992a"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-ftp-protocol"
|
|
||||||
packages = ["protocol"]
|
|
||||||
revision = "066b75c2b70dca7ae10b1b88b47534a3c31ccfaa"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-uuid"
|
|
||||||
packages = ["uuid"]
|
|
||||||
revision = "ed3ca8a15a931b141440a7e98e4f716eec255f7d"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-xz"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "0c531f070014e218b21f3cfca801cc992d52726d"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/lzma"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "7f0af6269940baa2c938fabe73e0d7ba41205683"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/syndtr/goleveldb"
|
|
||||||
packages = [
|
|
||||||
"leveldb",
|
|
||||||
"leveldb/cache",
|
|
||||||
"leveldb/comparer",
|
|
||||||
"leveldb/errors",
|
|
||||||
"leveldb/filter",
|
|
||||||
"leveldb/iterator",
|
|
||||||
"leveldb/journal",
|
|
||||||
"leveldb/memdb",
|
|
||||||
"leveldb/opt",
|
|
||||||
"leveldb/storage",
|
|
||||||
"leveldb/table",
|
|
||||||
"leveldb/util"
|
|
||||||
]
|
|
||||||
revision = "714f901b98fdb3aa954b4193d8cbd64a28d80cad"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/ugorji/go"
|
|
||||||
packages = ["codec"]
|
|
||||||
revision = "71c2886f5a673a35f909803f38ece5810165097b"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/wsxiaoys/terminal"
|
|
||||||
packages = ["color"]
|
|
||||||
revision = "0940f3fc43a0ed42d04916b1c04578462c650b09"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
packages = [
|
|
||||||
"cast5",
|
|
||||||
"openpgp",
|
|
||||||
"openpgp/armor",
|
|
||||||
"openpgp/clearsign",
|
|
||||||
"openpgp/elgamal",
|
|
||||||
"openpgp/errors",
|
|
||||||
"openpgp/packet",
|
|
||||||
"openpgp/s2k",
|
|
||||||
"ssh/terminal"
|
|
||||||
]
|
|
||||||
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = [
|
|
||||||
"unix",
|
|
||||||
"windows"
|
|
||||||
]
|
|
||||||
revision = "1d206c9fa8975fb4cf00df1dc8bf3283dc24ba0e"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "v1"
|
|
||||||
name = "gopkg.in/check.v1"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "gopkg.in/go-playground/validator.v8"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf"
|
|
||||||
version = "v8.18.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "gopkg.in/h2non/filetype.v1"
|
|
||||||
packages = ["types"]
|
|
||||||
revision = "3093b8ebec6efb56ac813238b8beab4ed4eaac6a"
|
|
||||||
version = "v1.0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "v2"
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "5ab2b384766e62be84d3941971a1d8e99c637f80a2cb1482b3d9704c668b549f"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/mkrautz/goar"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-uuid"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/smira/go-xz"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/ugorji/go"
|
|
||||||
revision = "71c2886f5a673a35f909803f38ece5810165097b"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "v1"
|
|
||||||
name = "gopkg.in/check.v1"
|
|
||||||
@@ -1,16 +1,22 @@
|
|||||||
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')
|
VERSION=$(shell git describe --tags | sed 's@^v@@' | sed 's@-@+@g')
|
||||||
PACKAGES=context database deb files gpg http query swift s3 utils
|
PACKAGES=context database deb files http query swift s3 utils
|
||||||
PYTHON?=python
|
PYTHON?=python
|
||||||
TESTS?=
|
TESTS?=
|
||||||
BINPATH?=$(GOPATH)/bin
|
BINPATH?=$(GOPATH)/bin
|
||||||
RUN_LONG_TESTS?=yes
|
|
||||||
|
|
||||||
GO_1_10_AND_HIGHER=$(shell (printf '%s\n' go1.10 $(GOVERSION) | sort -cV >/dev/null 2>&1) && echo "yes")
|
ifeq ($(GOVERSION), devel)
|
||||||
|
TRAVIS_TARGET=coveralls
|
||||||
|
else
|
||||||
|
TRAVIS_TARGET=test
|
||||||
|
endif
|
||||||
|
|
||||||
all: test check system-test
|
all: test check system-test
|
||||||
|
|
||||||
prepare:
|
prepare:
|
||||||
|
go get -u github.com/mattn/goveralls
|
||||||
|
go get -u github.com/axw/gocov/gocov
|
||||||
|
go get -u golang.org/x/tools/cmd/cover
|
||||||
go get -u github.com/alecthomas/gometalinter
|
go get -u github.com/alecthomas/gometalinter
|
||||||
gometalinter --install
|
gometalinter --install
|
||||||
|
|
||||||
@@ -18,50 +24,54 @@ dev:
|
|||||||
go get -u github.com/golang/dep/...
|
go get -u github.com/golang/dep/...
|
||||||
go get -u github.com/laher/goxc
|
go get -u github.com/laher/goxc
|
||||||
|
|
||||||
check: system/env
|
coverage.out:
|
||||||
ifeq ($(RUN_LONG_TESTS), yes)
|
rm -f coverage.*.out
|
||||||
if [ -x travis_wait ]; then \
|
for i in $(PACKAGES); do go test -coverprofile=coverage.$$i.out -covermode=count ./$$i; done
|
||||||
travis_wait gometalinter --config=linter.json ./...; \
|
echo "mode: count" > coverage.out
|
||||||
else \
|
grep -v -h "mode: count" coverage.*.out >> coverage.out
|
||||||
gometalinter --config=linter.json ./...; \
|
rm -f coverage.*.out
|
||||||
fi
|
|
||||||
. system/env/bin/activate && flake8 --max-line-length=200 --exclude=system/env/ system/
|
coverage: coverage.out
|
||||||
endif
|
go tool cover -html=coverage.out
|
||||||
|
rm -f coverage.out
|
||||||
|
|
||||||
|
check:
|
||||||
|
gometalinter --vendor --vendored-linters --config=linter.json ./...
|
||||||
|
|
||||||
install:
|
install:
|
||||||
go install -v -ldflags "-X main.Version=$(VERSION)"
|
go install -v -ldflags "-X main.Version=$(VERSION)"
|
||||||
|
|
||||||
system/env: system/requirements.txt
|
system-test: install
|
||||||
ifeq ($(RUN_LONG_TESTS), yes)
|
|
||||||
rm -rf system/env
|
|
||||||
virtualenv system/env
|
|
||||||
system/env/bin/pip install -r system/requirements.txt
|
|
||||||
endif
|
|
||||||
|
|
||||||
system-test: install system/env
|
|
||||||
ifeq ($(RUN_LONG_TESTS), yes)
|
|
||||||
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) && . system/env/bin/activate && APTLY_VERSION=$(VERSION) $(PYTHON) system/run.py --long $(TESTS)
|
APTLY_VERSION=$(VERSION) PATH=$(BINPATH)/:$(PATH) $(PYTHON) system/run.py --long $(TESTS)
|
||||||
endif
|
|
||||||
|
travis: $(TRAVIS_TARGET) check system-test
|
||||||
|
|
||||||
test:
|
test:
|
||||||
ifeq ($(GO_1_10_AND_HIGHER), yes)
|
|
||||||
go test -v ./... -gocheck.v=true -race -coverprofile=coverage.txt -covermode=atomic
|
|
||||||
else
|
|
||||||
go test -v `go list ./... | grep -v vendor/` -gocheck.v=true
|
go test -v `go list ./... | grep -v vendor/` -gocheck.v=true
|
||||||
endif
|
|
||||||
|
coveralls: coverage.out
|
||||||
|
$(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
|
||||||
open mem.png
|
open mem.png
|
||||||
|
|
||||||
|
src-package:
|
||||||
|
rm -rf aptly-$(VERSION)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
tar cyf aptly-$(VERSION)-src.tar.bz2 aptly-$(VERSION)
|
||||||
|
rm -rf aptly-$(VERSION)
|
||||||
|
|
||||||
goxc:
|
goxc:
|
||||||
rm -rf root/
|
rm -rf root/
|
||||||
mkdir -p root/usr/share/man/man1/ root/etc/bash_completion.d/ root/usr/share/zsh/vendor-completions/
|
mkdir -p root/usr/share/man/man1/ root/etc/bash_completion.d
|
||||||
cp man/aptly.1 root/usr/share/man/man1
|
cp man/aptly.1 root/usr/share/man/man1
|
||||||
cp completion.d/aptly root/etc/bash_completion.d/
|
(cd root/etc/bash_completion.d && wget https://raw.github.com/aptly-dev/aptly-bash-completion/master/aptly)
|
||||||
cp completion.d/_aptly root/usr/share/zsh/vendor-completions/
|
|
||||||
gzip root/usr/share/man/man1/aptly.1
|
gzip root/usr/share/man/man1/aptly.1
|
||||||
goxc -pv=$(VERSION) -max-processors=4 $(GOXC_OPTS)
|
goxc -pv=$(VERSION) -max-processors=4 $(GOXC_OPTS)
|
||||||
|
|
||||||
@@ -71,4 +81,4 @@ man:
|
|||||||
version:
|
version:
|
||||||
@echo $(VERSION)
|
@echo $(VERSION)
|
||||||
|
|
||||||
.PHONY: man version
|
.PHONY: coverage.out man version
|
||||||
|
|||||||
+14
-23
@@ -2,24 +2,24 @@
|
|||||||
aptly
|
aptly
|
||||||
=====
|
=====
|
||||||
|
|
||||||
.. image:: https://api.travis-ci.org/aptly-dev/aptly.svg?branch=master
|
.. image:: https://travis-ci.org/smira/aptly.png?branch=master
|
||||||
:target: https://travis-ci.org/aptly-dev/aptly
|
:target: https://travis-ci.org/smira/aptly
|
||||||
|
|
||||||
.. image:: https://codecov.io/gh/aptly-dev/aptly/branch/master/graph/badge.svg
|
.. image:: https://coveralls.io/repos/smira/aptly/badge.png?branch=HEAD
|
||||||
:target: https://codecov.io/gh/aptly-dev/aptly
|
:target: https://coveralls.io/r/smira/aptly?branch=HEAD
|
||||||
|
|
||||||
.. image:: https://badges.gitter.im/Join Chat.svg
|
.. image:: https://badges.gitter.im/Join Chat.svg
|
||||||
:target: https://gitter.im/aptly-dev/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/aptly-dev/aptly
|
.. image:: http://goreportcard.com/badge/smira/aptly
|
||||||
:target: http://goreportcard.com/report/aptly-dev/aptly
|
: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.
|
||||||
|
|
||||||
.. image:: http://www.aptly.info/img/aptly_logo.png
|
.. image:: http://www.aptly.info/img/aptly_logo.png
|
||||||
:target: http://www.aptly.info/
|
:target: http://www.aptly.info/
|
||||||
|
|
||||||
Documentation is available at `http://www.aptly.info/ <http://www.aptly.info/>`_. For support please use
|
Documentation is available at `http://www.aptly.info/ <http://www.aptly.info/>`_. For support use
|
||||||
mailing list `aptly-discuss <https://groups.google.com/forum/#!forum/aptly-discuss>`_.
|
mailing list `aptly-discuss <https://groups.google.com/forum/#!forum/aptly-discuss>`_.
|
||||||
|
|
||||||
Aptly features: ("+" means planned features)
|
Aptly features: ("+" means planned features)
|
||||||
@@ -42,13 +42,13 @@ Current limitations:
|
|||||||
Download
|
Download
|
||||||
--------
|
--------
|
||||||
|
|
||||||
To install aptly on Debian/Ubuntu, add new repository to ``/etc/apt/sources.list``::
|
To install aptly on Debian/Ubuntu, add new repository to /etc/apt/sources.list::
|
||||||
|
|
||||||
deb http://repo.aptly.info/ squeeze main
|
deb http://repo.aptly.info/ squeeze main
|
||||||
|
|
||||||
And import key that is used to sign the release::
|
And import key that is used to sign the release::
|
||||||
|
|
||||||
$ apt-key adv --keyserver pool.sks-keyservers.net --recv-keys ED75B5A4483DA07C
|
$ apt-key adv --keyserver keys.gnupg.net --recv-keys 9E3E53F19C7DE460
|
||||||
|
|
||||||
After that you can install aptly as any other software package::
|
After that you can install aptly as any other software package::
|
||||||
|
|
||||||
@@ -64,20 +64,15 @@ 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.8+ required)::
|
If you have Go environment set up, you can build aptly from source by running (go 1.6+ required)::
|
||||||
|
|
||||||
mkdir -p $GOPATH/src/github.com/aptly-dev/aptly
|
mkdir -p $GOPATH/src/github.com/smira/aptly
|
||||||
git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-dev/aptly
|
git clone https://github.com/smira/aptly $GOPATH/src/github.com/smira/aptly
|
||||||
cd $GOPATH/src/github.com/aptly-dev/aptly
|
cd $GOPATH/src/github.com/smira/aptly
|
||||||
make install
|
make install
|
||||||
|
|
||||||
Binary would be installed to ```$GOPATH/bin/aptly``.
|
Binary would be installed to ```$GOPATH/bin/aptly``.
|
||||||
|
|
||||||
Contributing
|
|
||||||
------------
|
|
||||||
|
|
||||||
Please follow detailed documentation in `CONTRIBUTING.md <CONTRIBUTING.md>`_.
|
|
||||||
|
|
||||||
Integrations
|
Integrations
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@@ -109,10 +104,6 @@ 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
|
- `Python aptly CLI (good for CI) <https://github.com/TimSusa/aptly_api_cli>`_ by Tim Susa
|
||||||
|
|
||||||
GUI for aptly API:
|
|
||||||
|
|
||||||
- `Python aptly GUI (via pyqt5) <https://github.com/chnyda/python-aptly-gui>`_ by Cedric Hnyda
|
|
||||||
|
|
||||||
Scala sbt:
|
Scala sbt:
|
||||||
|
|
||||||
- `sbt aptly plugin <https://github.com/amalakar/sbt-aptly>`_ by Arup Malakar
|
- `sbt aptly plugin <https://github.com/amalakar/sbt-aptly>`_ by Arup Malakar
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/cmd"
|
"github.com/smira/aptly/cmd"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|||||||
+28
-33
@@ -6,10 +6,10 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/aptly-dev/aptly/query"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/aptly"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
"github.com/smira/aptly/query"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lock order acquisition (canonical):
|
// Lock order acquisition (canonical):
|
||||||
@@ -23,18 +23,11 @@ func apiVersion(c *gin.Context) {
|
|||||||
c.JSON(200, gin.H{"Version": aptly.Version})
|
c.JSON(200, gin.H{"Version": aptly.Version})
|
||||||
}
|
}
|
||||||
|
|
||||||
type dbRequestKind int
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
acquiredb dbRequestKind = iota
|
acquiredb = iota
|
||||||
releasedb
|
releasedb
|
||||||
)
|
)
|
||||||
|
|
||||||
type dbRequest struct {
|
|
||||||
kind dbRequestKind
|
|
||||||
err chan<- error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flushes all collections which cache in-memory objects
|
// Flushes all collections which cache in-memory objects
|
||||||
func flushColections() {
|
func flushColections() {
|
||||||
// lock everything to eliminate in-progress calls
|
// lock everything to eliminate in-progress calls
|
||||||
@@ -59,48 +52,50 @@ func flushColections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Periodically flushes CollectionFactory to free up memory used by
|
// Periodically flushes CollectionFactory to free up memory used by
|
||||||
// collections, flushing caches.
|
// collections, flushing caches. If the two channels are provided,
|
||||||
|
// they are used to acquire and release the database.
|
||||||
//
|
//
|
||||||
// Should be run in goroutine!
|
// Should be run in goroutine!
|
||||||
func cacheFlusher() {
|
func cacheFlusher(requests chan int, acks chan error) {
|
||||||
ticker := time.Tick(15 * time.Minute)
|
ticker := time.Tick(15 * time.Minute)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
<-ticker
|
<-ticker
|
||||||
|
|
||||||
|
// if aptly API runs in -no-lock mode,
|
||||||
|
// caches are flushed when DB is closed anyway, no need
|
||||||
|
// to flush them here
|
||||||
|
if requests == nil {
|
||||||
flushColections()
|
flushColections()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire database lock and release it when not needed anymore.
|
// Acquire database lock and release it when not needed anymore. Two
|
||||||
|
// channels must be provided. The first one is to receive requests to
|
||||||
|
// acquire/release the database and the second one is to send acks.
|
||||||
//
|
//
|
||||||
// Should be run in a goroutine!
|
// Should be run in a goroutine!
|
||||||
func acquireDatabase(requests <-chan dbRequest) {
|
func acquireDatabase(requests chan int, acks chan error) {
|
||||||
clients := 0
|
clients := 0
|
||||||
for request := range requests {
|
for {
|
||||||
var err error
|
request := <-requests
|
||||||
|
switch request {
|
||||||
switch request.kind {
|
|
||||||
case acquiredb:
|
case acquiredb:
|
||||||
if clients == 0 {
|
if clients == 0 {
|
||||||
err = context.ReOpenDatabase()
|
acks <- context.ReOpenDatabase()
|
||||||
|
} else {
|
||||||
|
acks <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
request.err <- err
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
clients++
|
clients++
|
||||||
}
|
|
||||||
case releasedb:
|
case releasedb:
|
||||||
clients--
|
clients--
|
||||||
if clients == 0 {
|
if clients == 0 {
|
||||||
flushColections()
|
flushColections()
|
||||||
err = context.CloseDatabase()
|
acks <- context.CloseDatabase()
|
||||||
} else {
|
} else {
|
||||||
err = nil
|
acks <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
request.err <- err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +107,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList) {
|
|||||||
|
|
||||||
list, err := deb.NewPackageListFromRefList(reflist, context.CollectionFactory().PackageCollection(), nil)
|
list, err := deb.NewPackageListFromRefList(reflist, context.CollectionFactory().PackageCollection(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +115,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList) {
|
|||||||
if queryS != "" {
|
if queryS != "" {
|
||||||
q, err := query.Parse(c.Request.URL.Query().Get("q"))
|
q, err := query.Parse(c.Request.URL.Query().Get("q"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +132,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList) {
|
|||||||
sort.Strings(architecturesList)
|
sort.Strings(architecturesList)
|
||||||
|
|
||||||
if len(architecturesList) == 0 {
|
if len(architecturesList) == 0 {
|
||||||
c.AbortWithError(400, fmt.Errorf("unable to determine list of architectures, please specify explicitly"))
|
c.Fail(400, fmt.Errorf("unable to determine list of architectures, please specify explicitly"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +142,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList) {
|
|||||||
list, err = list.Filter([]deb.PackageQuery{q}, withDeps,
|
list, err = list.Filter([]deb.PackageQuery{q}, withDeps,
|
||||||
nil, context.DependencyOptions(), architecturesList)
|
nil, context.DependencyOptions(), architecturesList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to search: %s", err))
|
c.Fail(500, fmt.Errorf("unable to search: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -24,7 +24,7 @@ func verifyPath(path string) bool {
|
|||||||
|
|
||||||
func verifyDir(c *gin.Context) bool {
|
func verifyDir(c *gin.Context) bool {
|
||||||
if !verifyPath(c.Params.ByName("dir")) {
|
if !verifyPath(c.Params.ByName("dir")) {
|
||||||
c.AbortWithError(400, fmt.Errorf("wrong dir"))
|
c.Fail(400, fmt.Errorf("wrong dir"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ func apiFilesListDirs(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +70,13 @@ func apiFilesUpload(c *gin.Context) {
|
|||||||
err := os.MkdirAll(path, 0777)
|
err := os.MkdirAll(path, 0777)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.Request.ParseMultipartForm(10 * 1024 * 1024)
|
err = c.Request.ParseMultipartForm(10 * 1024 * 1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ func apiFilesUpload(c *gin.Context) {
|
|||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
src, err := file.Open()
|
src, err := file.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
@@ -94,14 +94,14 @@ func apiFilesUpload(c *gin.Context) {
|
|||||||
destPath := filepath.Join(path, filepath.Base(file.Filename))
|
destPath := filepath.Join(path, filepath.Base(file.Filename))
|
||||||
dst, err := os.Create(destPath)
|
dst, err := os.Create(destPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer dst.Close()
|
defer dst.Close()
|
||||||
|
|
||||||
_, err = io.Copy(dst, src)
|
_, err = io.Copy(dst, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +138,9 @@ func apiFilesListFiles(c *gin.Context) {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ func apiFilesDeleteDir(c *gin.Context) {
|
|||||||
|
|
||||||
err := os.RemoveAll(filepath.Join(context.UploadPath(), c.Params.ByName("dir")))
|
err := os.RemoveAll(filepath.Join(context.UploadPath(), c.Params.ByName("dir")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,14 +170,14 @@ func apiFilesDeleteFile(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !verifyPath(c.Params.ByName("name")) {
|
if !verifyPath(c.Params.ByName("name")) {
|
||||||
c.AbortWithError(400, fmt.Errorf("wrong file"))
|
c.Fail(400, fmt.Errorf("wrong file"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := os.Remove(filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("name")))
|
err := os.Remove(filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("name")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err1, ok := err.(*os.PathError); !ok || !os.IsNotExist(err1.Err) {
|
if err1, ok := err.(*os.PathError); !ok || !os.IsNotExist(err1.Err) {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -8,8 +8,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET /api/graph.:ext?layout=[vertical|horizontal(default)]
|
// GET /api/graph.:ext?layout=[vertical|horizontal(default)]
|
||||||
@@ -24,14 +24,14 @@ func apiGraph(c *gin.Context) {
|
|||||||
|
|
||||||
factory := context.CollectionFactory()
|
factory := context.CollectionFactory()
|
||||||
|
|
||||||
factory.RemoteRepoCollection().Lock()
|
factory.RemoteRepoCollection().RLock()
|
||||||
defer factory.RemoteRepoCollection().Unlock()
|
defer factory.RemoteRepoCollection().RUnlock()
|
||||||
factory.LocalRepoCollection().Lock()
|
factory.LocalRepoCollection().RLock()
|
||||||
defer factory.LocalRepoCollection().Unlock()
|
defer factory.LocalRepoCollection().RUnlock()
|
||||||
factory.SnapshotCollection().Lock()
|
factory.SnapshotCollection().RLock()
|
||||||
defer factory.SnapshotCollection().Unlock()
|
defer factory.SnapshotCollection().RUnlock()
|
||||||
factory.PublishedRepoCollection().Lock()
|
factory.PublishedRepoCollection().RLock()
|
||||||
defer factory.PublishedRepoCollection().Unlock()
|
defer factory.PublishedRepoCollection().RUnlock()
|
||||||
|
|
||||||
graph, err := deb.BuildGraph(factory, layout)
|
graph, err := deb.BuildGraph(factory, layout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -53,25 +53,25 @@ func apiGraph(c *gin.Context) {
|
|||||||
|
|
||||||
stdin, err := command.StdinPipe()
|
stdin, err := command.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.Copy(stdin, buf)
|
_, err = io.Copy(stdin, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = stdin.Close()
|
err = stdin.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err = command.Output()
|
output, err = command.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err))
|
c.Fail(500, fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ import (
|
|||||||
func apiPackagesShow(c *gin.Context) {
|
func apiPackagesShow(c *gin.Context) {
|
||||||
p, err := context.CollectionFactory().PackageCollection().ByKey([]byte(c.Params.ByName("key")))
|
p, err := context.CollectionFactory().PackageCollection().ByKey([]byte(c.Params.ByName("key")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
-73
@@ -4,10 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SigningOptions is a shared between publish API GPG options structure
|
// SigningOptions is a shared between publish API GPG options structure
|
||||||
@@ -21,12 +20,12 @@ type SigningOptions struct {
|
|||||||
PassphraseFile string
|
PassphraseFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSigner(options *SigningOptions) (pgp.Signer, error) {
|
func getSigner(options *SigningOptions) (utils.Signer, error) {
|
||||||
if options.Skip {
|
if options.Skip {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
signer := context.GetSigner()
|
signer := &utils.GpgSigner{}
|
||||||
signer.SetKey(options.GpgKey)
|
signer.SetKey(options.GpgKey)
|
||||||
signer.SetKeyRing(options.Keyring, options.SecretKeyring)
|
signer.SetKeyRing(options.Keyring, options.SecretKeyring)
|
||||||
signer.SetPassphrase(options.Passphrase, options.PassphraseFile)
|
signer.SetPassphrase(options.Passphrase, options.PassphraseFile)
|
||||||
@@ -60,8 +59,8 @@ func apiPublishList(c *gin.Context) {
|
|||||||
defer snapshotCollection.RUnlock()
|
defer snapshotCollection.RUnlock()
|
||||||
|
|
||||||
collection := context.CollectionFactory().PublishedRepoCollection()
|
collection := context.CollectionFactory().PublishedRepoCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
result := make([]*deb.PublishedRepo, 0, collection.Len())
|
result := make([]*deb.PublishedRepo, 0, collection.Len())
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ func apiPublishList(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,27 +97,24 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
|||||||
Distribution string
|
Distribution string
|
||||||
Label string
|
Label string
|
||||||
Origin string
|
Origin string
|
||||||
NotAutomatic string
|
|
||||||
ButAutomaticUpgrades string
|
|
||||||
ForceOverwrite bool
|
ForceOverwrite bool
|
||||||
SkipContents *bool
|
SkipContents *bool
|
||||||
Architectures []string
|
Architectures []string
|
||||||
Signing SigningOptions
|
Signing SigningOptions
|
||||||
AcquireByHash *bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := getSigner(&b.Signing)
|
signer, err := getSigner(&b.Signing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to initialize GPG signer: %s", err))
|
c.Fail(500, fmt.Errorf("unable to initialize GPG signer: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b.Sources) == 0 {
|
if len(b.Sources) == 0 {
|
||||||
c.AbortWithError(400, fmt.Errorf("unable to publish: soures are empty"))
|
c.Fail(400, fmt.Errorf("unable to publish: soures are empty"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,51 +125,51 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
|||||||
var snapshot *deb.Snapshot
|
var snapshot *deb.Snapshot
|
||||||
|
|
||||||
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
||||||
snapshotCollection.Lock()
|
snapshotCollection.RLock()
|
||||||
defer snapshotCollection.Unlock()
|
defer snapshotCollection.RUnlock()
|
||||||
|
|
||||||
for _, source := range b.Sources {
|
for _, source := range b.Sources {
|
||||||
components = append(components, source.Component)
|
components = append(components, source.Component)
|
||||||
|
|
||||||
snapshot, err = snapshotCollection.ByName(source.Name)
|
snapshot, err = snapshotCollection.ByName(source.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(404, fmt.Errorf("unable to publish: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snapshotCollection.LoadComplete(snapshot)
|
err = snapshotCollection.LoadComplete(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(500, fmt.Errorf("unable to publish: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sources = append(sources, snapshot)
|
sources = append(sources, snapshot)
|
||||||
}
|
}
|
||||||
} else if b.SourceKind == deb.SourceLocalRepo {
|
} else if b.SourceKind == "local" {
|
||||||
var localRepo *deb.LocalRepo
|
var localRepo *deb.LocalRepo
|
||||||
|
|
||||||
localCollection := context.CollectionFactory().LocalRepoCollection()
|
localCollection := context.CollectionFactory().LocalRepoCollection()
|
||||||
localCollection.Lock()
|
localCollection.RLock()
|
||||||
defer localCollection.Unlock()
|
defer localCollection.RUnlock()
|
||||||
|
|
||||||
for _, source := range b.Sources {
|
for _, source := range b.Sources {
|
||||||
components = append(components, source.Component)
|
components = append(components, source.Component)
|
||||||
|
|
||||||
localRepo, err = localCollection.ByName(source.Name)
|
localRepo, err = localCollection.ByName(source.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(404, fmt.Errorf("unable to publish: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = localCollection.LoadComplete(localRepo)
|
err = localCollection.LoadComplete(localRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(500, fmt.Errorf("unable to publish: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
sources = append(sources, localRepo)
|
sources = append(sources, localRepo)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithError(400, fmt.Errorf("unknown SourceKind"))
|
c.Fail(400, fmt.Errorf("unknown SourceKind"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,18 +179,10 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
|||||||
|
|
||||||
published, err := deb.NewPublishedRepo(storage, prefix, b.Distribution, b.Architectures, components, sources, context.CollectionFactory())
|
published, err := deb.NewPublishedRepo(storage, prefix, b.Distribution, b.Architectures, components, sources, context.CollectionFactory())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(500, fmt.Errorf("unable to publish: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b.Origin != "" {
|
|
||||||
published.Origin = b.Origin
|
published.Origin = b.Origin
|
||||||
}
|
|
||||||
if b.NotAutomatic != "" {
|
|
||||||
published.NotAutomatic = b.NotAutomatic
|
|
||||||
}
|
|
||||||
if b.ButAutomaticUpgrades != "" {
|
|
||||||
published.ButAutomaticUpgrades = b.ButAutomaticUpgrades
|
|
||||||
}
|
|
||||||
published.Label = b.Label
|
published.Label = b.Label
|
||||||
|
|
||||||
published.SkipContents = context.Config().SkipContentsPublishing
|
published.SkipContents = context.Config().SkipContentsPublishing
|
||||||
@@ -202,26 +190,22 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
|||||||
published.SkipContents = *b.SkipContents
|
published.SkipContents = *b.SkipContents
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.AcquireByHash != nil {
|
|
||||||
published.AcquireByHash = *b.AcquireByHash
|
|
||||||
}
|
|
||||||
|
|
||||||
duplicate := collection.CheckDuplicate(published)
|
duplicate := collection.CheckDuplicate(published)
|
||||||
if duplicate != nil {
|
if duplicate != nil {
|
||||||
context.CollectionFactory().PublishedRepoCollection().LoadComplete(duplicate, context.CollectionFactory())
|
context.CollectionFactory().PublishedRepoCollection().LoadComplete(duplicate, context.CollectionFactory())
|
||||||
c.AbortWithError(400, fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate))
|
c.Fail(400, fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, nil, b.ForceOverwrite)
|
err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, nil, b.ForceOverwrite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to publish: %s", err))
|
c.Fail(500, fmt.Errorf("unable to publish: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.Add(published)
|
err = collection.Add(published)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to save to DB: %s", err))
|
c.Fail(500, fmt.Errorf("unable to save to DB: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,32 +222,30 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
ForceOverwrite bool
|
ForceOverwrite bool
|
||||||
Signing SigningOptions
|
Signing SigningOptions
|
||||||
SkipContents *bool
|
SkipContents *bool
|
||||||
SkipCleanup *bool
|
|
||||||
Snapshots []struct {
|
Snapshots []struct {
|
||||||
Component string `binding:"required"`
|
Component string `binding:"required"`
|
||||||
Name string `binding:"required"`
|
Name string `binding:"required"`
|
||||||
}
|
}
|
||||||
AcquireByHash *bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := getSigner(&b.Signing)
|
signer, err := getSigner(&b.Signing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to initialize GPG signer: %s", err))
|
c.Fail(500, fmt.Errorf("unable to initialize GPG signer: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// published.LoadComplete would touch local repo collection
|
// published.LoadComplete would touch local repo collection
|
||||||
localRepoCollection := context.CollectionFactory().LocalRepoCollection()
|
localRepoCollection := context.CollectionFactory().LocalRepoCollection()
|
||||||
localRepoCollection.Lock()
|
localRepoCollection.RLock()
|
||||||
defer localRepoCollection.Unlock()
|
defer localRepoCollection.RUnlock()
|
||||||
|
|
||||||
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
||||||
snapshotCollection.Lock()
|
snapshotCollection.RLock()
|
||||||
defer snapshotCollection.Unlock()
|
defer snapshotCollection.RUnlock()
|
||||||
|
|
||||||
collection := context.CollectionFactory().PublishedRepoCollection()
|
collection := context.CollectionFactory().PublishedRepoCollection()
|
||||||
collection.Lock()
|
collection.Lock()
|
||||||
@@ -271,20 +253,20 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
|
|
||||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, fmt.Errorf("unable to update: %s", err))
|
c.Fail(404, fmt.Errorf("unable to update: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = collection.LoadComplete(published, context.CollectionFactory())
|
err = collection.LoadComplete(published, context.CollectionFactory())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to update: %s", err))
|
c.Fail(500, fmt.Errorf("unable to update: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var updatedComponents []string
|
var updatedComponents []string
|
||||||
|
|
||||||
if published.SourceKind == deb.SourceLocalRepo {
|
if published.SourceKind == "local" {
|
||||||
if len(b.Snapshots) > 0 {
|
if len(b.Snapshots) > 0 {
|
||||||
c.AbortWithError(400, fmt.Errorf("snapshots shouldn't be given when updating local repo"))
|
c.Fail(400, fmt.Errorf("snapshots shouldn't be given when updating local repo"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updatedComponents = published.Components()
|
updatedComponents = published.Components()
|
||||||
@@ -295,19 +277,19 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
publishedComponents := published.Components()
|
publishedComponents := published.Components()
|
||||||
for _, snapshotInfo := range b.Snapshots {
|
for _, snapshotInfo := range b.Snapshots {
|
||||||
if !utils.StrSliceHasItem(publishedComponents, snapshotInfo.Component) {
|
if !utils.StrSliceHasItem(publishedComponents, snapshotInfo.Component) {
|
||||||
c.AbortWithError(404, fmt.Errorf("component %s is not in published repository", snapshotInfo.Component))
|
c.Fail(404, fmt.Errorf("component %s is not in published repository", snapshotInfo.Component))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot, err2 := snapshotCollection.ByName(snapshotInfo.Name)
|
snapshot, err := snapshotCollection.ByName(snapshotInfo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err2)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err2 = snapshotCollection.LoadComplete(snapshot)
|
err = snapshotCollection.LoadComplete(snapshot)
|
||||||
if err2 != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err2)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +297,7 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
updatedComponents = append(updatedComponents, snapshotInfo.Component)
|
updatedComponents = append(updatedComponents, snapshotInfo.Component)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithError(500, fmt.Errorf("unknown published repository type"))
|
c.Fail(500, fmt.Errorf("unknown published repository type"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,30 +305,24 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
published.SkipContents = *b.SkipContents
|
published.SkipContents = *b.SkipContents
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.AcquireByHash != nil {
|
|
||||||
published.AcquireByHash = *b.AcquireByHash
|
|
||||||
}
|
|
||||||
|
|
||||||
err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, nil, b.ForceOverwrite)
|
err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, nil, b.ForceOverwrite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to update: %s", err))
|
c.Fail(500, fmt.Errorf("unable to update: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.Update(published)
|
err = collection.Update(published)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to save to DB: %s", err))
|
c.Fail(500, fmt.Errorf("unable to save to DB: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.SkipCleanup == nil || !*b.SkipCleanup {
|
|
||||||
err = collection.CleanupPrefixComponentFiles(published.Prefix, updatedComponents,
|
err = collection.CleanupPrefixComponentFiles(published.Prefix, updatedComponents,
|
||||||
context.GetPublishedStorage(storage), context.CollectionFactory(), nil)
|
context.GetPublishedStorage(storage), context.CollectionFactory(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to update: %s", err))
|
c.Fail(500, fmt.Errorf("unable to update: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(200, published)
|
c.JSON(200, published)
|
||||||
}
|
}
|
||||||
@@ -354,7 +330,6 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
|||||||
// DELETE /publish/:prefix/:distribution
|
// DELETE /publish/:prefix/:distribution
|
||||||
func apiPublishDrop(c *gin.Context) {
|
func apiPublishDrop(c *gin.Context) {
|
||||||
force := c.Request.URL.Query().Get("force") == "1"
|
force := c.Request.URL.Query().Get("force") == "1"
|
||||||
skipCleanup := c.Request.URL.Query().Get("SkipCleanup") == "1"
|
|
||||||
|
|
||||||
param := parseEscapedPath(c.Params.ByName("prefix"))
|
param := parseEscapedPath(c.Params.ByName("prefix"))
|
||||||
storage, prefix := deb.ParsePrefix(param)
|
storage, prefix := deb.ParsePrefix(param)
|
||||||
@@ -362,17 +337,17 @@ func apiPublishDrop(c *gin.Context) {
|
|||||||
|
|
||||||
// published.LoadComplete would touch local repo collection
|
// published.LoadComplete would touch local repo collection
|
||||||
localRepoCollection := context.CollectionFactory().LocalRepoCollection()
|
localRepoCollection := context.CollectionFactory().LocalRepoCollection()
|
||||||
localRepoCollection.Lock()
|
localRepoCollection.RLock()
|
||||||
defer localRepoCollection.Unlock()
|
defer localRepoCollection.RUnlock()
|
||||||
|
|
||||||
collection := context.CollectionFactory().PublishedRepoCollection()
|
collection := context.CollectionFactory().PublishedRepoCollection()
|
||||||
collection.Lock()
|
collection.Lock()
|
||||||
defer collection.Unlock()
|
defer collection.Unlock()
|
||||||
|
|
||||||
err := collection.Remove(context, storage, prefix, distribution,
|
err := collection.Remove(context, storage, prefix, distribution,
|
||||||
context.CollectionFactory(), context.Progress(), force, skipCleanup)
|
context.CollectionFactory(), context.Progress(), force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to drop: %s", err))
|
c.Fail(500, fmt.Errorf("unable to drop: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-38
@@ -5,11 +5,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/aptly"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET /api/repos
|
// GET /api/repos
|
||||||
@@ -37,7 +37,7 @@ func apiReposCreate(c *gin.Context) {
|
|||||||
DefaultComponent string
|
DefaultComponent string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func apiReposCreate(c *gin.Context) {
|
|||||||
|
|
||||||
err := context.CollectionFactory().LocalRepoCollection().Add(repo)
|
err := context.CollectionFactory().LocalRepoCollection().Add(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ func apiReposEdit(c *gin.Context) {
|
|||||||
DefaultComponent *string
|
DefaultComponent *string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ func apiReposEdit(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ func apiReposEdit(c *gin.Context) {
|
|||||||
|
|
||||||
err = collection.Update(repo)
|
err = collection.Update(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ func apiReposShow(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,27 +132,27 @@ func apiReposDrop(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
published := publishedCollection.ByLocalRepo(repo)
|
published := publishedCollection.ByLocalRepo(repo)
|
||||||
if len(published) > 0 {
|
if len(published) > 0 {
|
||||||
c.AbortWithError(409, fmt.Errorf("unable to drop, local repo is published"))
|
c.Fail(409, fmt.Errorf("unable to drop, local repo is published"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !force {
|
if !force {
|
||||||
snapshots := snapshotCollection.ByLocalRepoSource(repo)
|
snapshots := snapshotCollection.ByLocalRepoSource(repo)
|
||||||
if len(snapshots) > 0 {
|
if len(snapshots) > 0 {
|
||||||
c.AbortWithError(409, fmt.Errorf("unable to drop, local repo has snapshots, use ?force=1 to override"))
|
c.Fail(409, fmt.Errorf("unable to drop, local repo has snapshots, use ?force=1 to override"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.Drop(repo)
|
err = collection.Drop(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,18 +162,18 @@ func apiReposDrop(c *gin.Context) {
|
|||||||
// GET /api/repos/:name/packages
|
// GET /api/repos/:name/packages
|
||||||
func apiReposPackagesShow(c *gin.Context) {
|
func apiReposPackagesShow(c *gin.Context) {
|
||||||
collection := context.CollectionFactory().LocalRepoCollection()
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(repo)
|
err = collection.LoadComplete(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ func apiReposPackagesAddDelete(c *gin.Context, cb func(list *deb.PackageList, p
|
|||||||
PackageRefs []string
|
PackageRefs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,19 +196,19 @@ func apiReposPackagesAddDelete(c *gin.Context, cb func(list *deb.PackageList, p
|
|||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(repo)
|
err = collection.LoadComplete(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
|
list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,15 +219,15 @@ func apiReposPackagesAddDelete(c *gin.Context, cb func(list *deb.PackageList, p
|
|||||||
p, err = context.CollectionFactory().PackageCollection().ByKey([]byte(ref))
|
p, err = context.CollectionFactory().PackageCollection().ByKey([]byte(ref))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == database.ErrNotFound {
|
if err == database.ErrNotFound {
|
||||||
c.AbortWithError(404, fmt.Errorf("package %s: %s", ref, err))
|
c.Fail(404, fmt.Errorf("package %s: %s", ref, err))
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cb(list, p)
|
err = cb(list, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ func apiReposPackagesAddDelete(c *gin.Context, cb func(list *deb.PackageList, p
|
|||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to save: %s", err))
|
c.Fail(500, fmt.Errorf("unable to save: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ func apiReposPackageFromDir(c *gin.Context) {
|
|||||||
|
|
||||||
fileParam := c.Params.ByName("file")
|
fileParam := c.Params.ByName("file")
|
||||||
if fileParam != "" && !verifyPath(fileParam) {
|
if fileParam != "" && !verifyPath(fileParam) {
|
||||||
c.AbortWithError(400, fmt.Errorf("wrong file"))
|
c.Fail(400, fmt.Errorf("wrong file"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,22 +286,21 @@ func apiReposPackageFromDir(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err := collection.ByName(c.Params.ByName("name"))
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(repo)
|
err = collection.LoadComplete(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
verifier := context.GetVerifier()
|
verifier := &utils.GpgVerifier{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
sources []string
|
sources []string
|
||||||
packageFiles, failedFiles []string
|
packageFiles, failedFiles []string
|
||||||
otherFiles []string
|
|
||||||
processedFiles, failedFiles2 []string
|
processedFiles, failedFiles2 []string
|
||||||
reporter = &aptly.RecordingResultReporter{
|
reporter = &aptly.RecordingResultReporter{
|
||||||
Warnings: []string{},
|
Warnings: []string{},
|
||||||
@@ -317,22 +316,20 @@ func apiReposPackageFromDir(c *gin.Context) {
|
|||||||
sources = []string{filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("file"))}
|
sources = []string{filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("file"))}
|
||||||
}
|
}
|
||||||
|
|
||||||
packageFiles, otherFiles, failedFiles = deb.CollectPackageFiles(sources, reporter)
|
packageFiles, failedFiles = deb.CollectPackageFiles(sources, reporter)
|
||||||
|
|
||||||
list, err = deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
|
list, err = deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to load packages: %s", err))
|
c.Fail(500, fmt.Errorf("unable to load packages: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
||||||
context.CollectionFactory().PackageCollection(), reporter, nil, context.CollectionFactory().ChecksumCollection())
|
context.CollectionFactory().PackageCollection(), reporter, nil)
|
||||||
failedFiles = append(failedFiles, failedFiles2...)
|
failedFiles = append(failedFiles, failedFiles2...)
|
||||||
|
|
||||||
processedFiles = append(processedFiles, otherFiles...)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to import package files: %s", err))
|
c.Fail(500, fmt.Errorf("unable to import package files: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +337,7 @@ func apiReposPackageFromDir(c *gin.Context) {
|
|||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, fmt.Errorf("unable to save: %s", err))
|
c.Fail(500, fmt.Errorf("unable to save: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-16
@@ -3,8 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
ctx "github.com/aptly-dev/aptly/context"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
ctx "github.com/smira/aptly/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var context *ctx.AptlyContext
|
var context *ctx.AptlyContext
|
||||||
@@ -20,35 +20,32 @@ func Router(c *ctx.AptlyContext) http.Handler {
|
|||||||
// We use a goroutine to count the number of
|
// We use a goroutine to count the number of
|
||||||
// concurrent requests. When no more requests are
|
// concurrent requests. When no more requests are
|
||||||
// running, we close the database to free the lock.
|
// running, we close the database to free the lock.
|
||||||
requests := make(chan dbRequest)
|
requests := make(chan int)
|
||||||
|
acks := make(chan error)
|
||||||
|
|
||||||
go acquireDatabase(requests)
|
go acquireDatabase(requests, acks)
|
||||||
|
go cacheFlusher(requests, acks)
|
||||||
|
|
||||||
router.Use(func(c *gin.Context) {
|
router.Use(func(c *gin.Context) {
|
||||||
var err error
|
requests <- acquiredb
|
||||||
|
err := <-acks
|
||||||
errCh := make(chan error)
|
|
||||||
requests <- dbRequest{acquiredb, errCh}
|
|
||||||
|
|
||||||
err = <-errCh
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
requests <- dbRequest{releasedb, errCh}
|
requests <- releasedb
|
||||||
err = <-errCh
|
err = <-acks
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c.Next()
|
c.Next()
|
||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
go cacheFlusher()
|
go cacheFlusher(nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
root := router.Group("/api")
|
root := router.Group("/api")
|
||||||
|
|||||||
+47
-47
@@ -3,9 +3,9 @@ package api
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET /api/snapshots
|
// GET /api/snapshots
|
||||||
@@ -42,13 +42,13 @@ func apiSnapshotsCreateFromMirror(c *gin.Context) {
|
|||||||
Description string
|
Description string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := context.CollectionFactory().RemoteRepoCollection()
|
collection := context.CollectionFactory().RemoteRepoCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
||||||
snapshotCollection.Lock()
|
snapshotCollection.Lock()
|
||||||
@@ -56,25 +56,25 @@ func apiSnapshotsCreateFromMirror(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err = collection.ByName(c.Params.ByName("name"))
|
repo, err = collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.CheckLock()
|
err = repo.CheckLock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(409, err)
|
c.Fail(409, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(repo)
|
err = collection.LoadComplete(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot, err = deb.NewSnapshotFromRepository(b.Name, repo)
|
snapshot, err = deb.NewSnapshotFromRepository(b.Name, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ func apiSnapshotsCreateFromMirror(c *gin.Context) {
|
|||||||
|
|
||||||
err = snapshotCollection.Add(snapshot)
|
err = snapshotCollection.Add(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ func apiSnapshotsCreate(c *gin.Context) {
|
|||||||
PackageRefs []string
|
PackageRefs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,13 +124,13 @@ func apiSnapshotsCreate(c *gin.Context) {
|
|||||||
for i := range b.SourceSnapshots {
|
for i := range b.SourceSnapshots {
|
||||||
sources[i], err = snapshotCollection.ByName(b.SourceSnapshots[i])
|
sources[i], err = snapshotCollection.ByName(b.SourceSnapshots[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snapshotCollection.LoadComplete(sources[i])
|
err = snapshotCollection.LoadComplete(sources[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,15 +144,15 @@ func apiSnapshotsCreate(c *gin.Context) {
|
|||||||
p, err = context.CollectionFactory().PackageCollection().ByKey([]byte(ref))
|
p, err = context.CollectionFactory().PackageCollection().ByKey([]byte(ref))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == database.ErrNotFound {
|
if err == database.ErrNotFound {
|
||||||
c.AbortWithError(404, fmt.Errorf("package %s: %s", ref, err))
|
c.Fail(404, fmt.Errorf("package %s: %s", ref, err))
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = list.Add(p)
|
err = list.Add(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ func apiSnapshotsCreate(c *gin.Context) {
|
|||||||
|
|
||||||
err = snapshotCollection.Add(snapshot)
|
err = snapshotCollection.Add(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,13 +181,13 @@ func apiSnapshotsCreateFromRepository(c *gin.Context) {
|
|||||||
Description string
|
Description string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := context.CollectionFactory().LocalRepoCollection()
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
||||||
snapshotCollection.Lock()
|
snapshotCollection.Lock()
|
||||||
@@ -195,19 +195,19 @@ func apiSnapshotsCreateFromRepository(c *gin.Context) {
|
|||||||
|
|
||||||
repo, err = collection.ByName(c.Params.ByName("name"))
|
repo, err = collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(repo)
|
err = collection.LoadComplete(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot, err = deb.NewSnapshotFromLocalRepo(b.Name, repo)
|
snapshot, err = deb.NewSnapshotFromLocalRepo(b.Name, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ func apiSnapshotsCreateFromRepository(c *gin.Context) {
|
|||||||
|
|
||||||
err = snapshotCollection.Add(snapshot)
|
err = snapshotCollection.Add(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(400, err)
|
c.Fail(400, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ func apiSnapshotsUpdate(c *gin.Context) {
|
|||||||
Description string
|
Description string
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bind(&b) != nil {
|
if !c.Bind(&b) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,13 +246,13 @@ func apiSnapshotsUpdate(c *gin.Context) {
|
|||||||
|
|
||||||
snapshot, err = collection.ByName(c.Params.ByName("name"))
|
snapshot, err = collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = collection.ByName(b.Name)
|
_, err = collection.ByName(b.Name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.AbortWithError(409, fmt.Errorf("unable to rename: snapshot %s already exists", b.Name))
|
c.Fail(409, fmt.Errorf("unable to rename: snapshot %s already exists", b.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ func apiSnapshotsUpdate(c *gin.Context) {
|
|||||||
|
|
||||||
err = context.CollectionFactory().SnapshotCollection().Update(snapshot)
|
err = context.CollectionFactory().SnapshotCollection().Update(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,18 +276,18 @@ func apiSnapshotsUpdate(c *gin.Context) {
|
|||||||
// GET /api/snapshots/:name
|
// GET /api/snapshots/:name
|
||||||
func apiSnapshotsShow(c *gin.Context) {
|
func apiSnapshotsShow(c *gin.Context) {
|
||||||
collection := context.CollectionFactory().SnapshotCollection()
|
collection := context.CollectionFactory().SnapshotCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
snapshot, err := collection.ByName(c.Params.ByName("name"))
|
snapshot, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(snapshot)
|
err = collection.LoadComplete(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,28 +309,28 @@ func apiSnapshotsDrop(c *gin.Context) {
|
|||||||
|
|
||||||
snapshot, err := snapshotCollection.ByName(name)
|
snapshot, err := snapshotCollection.ByName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
published := publishedCollection.BySnapshot(snapshot)
|
published := publishedCollection.BySnapshot(snapshot)
|
||||||
|
|
||||||
if len(published) > 0 {
|
if len(published) > 0 {
|
||||||
c.AbortWithError(409, fmt.Errorf("unable to drop: snapshot is published"))
|
c.Fail(409, fmt.Errorf("unable to drop: snapshot is published"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !force {
|
if !force {
|
||||||
snapshots := snapshotCollection.BySnapshotSource(snapshot)
|
snapshots := snapshotCollection.BySnapshotSource(snapshot)
|
||||||
if len(snapshots) > 0 {
|
if len(snapshots) > 0 {
|
||||||
c.AbortWithError(409, fmt.Errorf("won't delete snapshot that was used as source for other snapshots, use ?force=1 to override"))
|
c.Fail(409, fmt.Errorf("won't delete snapshot that was used as source for other snapshots, use ?force=1 to override"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snapshotCollection.Drop(snapshot)
|
err = snapshotCollection.Drop(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,37 +342,37 @@ func apiSnapshotsDiff(c *gin.Context) {
|
|||||||
onlyMatching := c.Request.URL.Query().Get("onlyMatching") == "1"
|
onlyMatching := c.Request.URL.Query().Get("onlyMatching") == "1"
|
||||||
|
|
||||||
collection := context.CollectionFactory().SnapshotCollection()
|
collection := context.CollectionFactory().SnapshotCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
snapshotA, err := collection.ByName(c.Params.ByName("name"))
|
snapshotA, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshotB, err := collection.ByName(c.Params.ByName("withSnapshot"))
|
snapshotB, err := collection.ByName(c.Params.ByName("withSnapshot"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(snapshotA)
|
err = collection.LoadComplete(snapshotA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(snapshotB)
|
err = collection.LoadComplete(snapshotB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate diff
|
// Calculate diff
|
||||||
diff, err := snapshotA.RefList().Diff(snapshotB.RefList(), context.CollectionFactory().PackageCollection())
|
diff, err := snapshotA.RefList().Diff(snapshotB.RefList(), context.CollectionFactory().PackageCollection())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,18 +392,18 @@ func apiSnapshotsDiff(c *gin.Context) {
|
|||||||
// GET /api/snapshots/:name/packages
|
// GET /api/snapshots/:name/packages
|
||||||
func apiSnapshotsSearchPackages(c *gin.Context) {
|
func apiSnapshotsSearchPackages(c *gin.Context) {
|
||||||
collection := context.CollectionFactory().SnapshotCollection()
|
collection := context.CollectionFactory().SnapshotCollection()
|
||||||
collection.Lock()
|
collection.RLock()
|
||||||
defer collection.Unlock()
|
defer collection.RUnlock()
|
||||||
|
|
||||||
snapshot, err := collection.ByName(c.Params.ByName("name"))
|
snapshot, err := collection.ByName(c.Params.ByName("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(404, err)
|
c.Fail(404, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = collection.LoadComplete(snapshot)
|
err = collection.LoadComplete(snapshot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.Fail(500, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=APT repository API
|
|
||||||
After=network.target
|
|
||||||
Documentation=man:aptly(1)
|
|
||||||
Documentation=https://www.aptly.info/doc/api/
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/bin/aptly serve api -no-lock -listen=127.0.0.1:8081
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=APT repository server
|
|
||||||
After=network.target
|
|
||||||
Documentation=man:aptly(1)
|
|
||||||
Documentation=https://www.aptly.info/doc/commands/
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/bin/aptly serve -listen=127.0.0.1:8080
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
+21
-64
@@ -3,59 +3,25 @@
|
|||||||
package aptly
|
package aptly
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadSeekerCloser = ReadSeeker + Closer
|
|
||||||
type ReadSeekerCloser interface {
|
|
||||||
io.ReadSeeker
|
|
||||||
io.Closer
|
|
||||||
}
|
|
||||||
|
|
||||||
// PackagePool is asbtraction of package pool storage.
|
// PackagePool is asbtraction of package pool storage.
|
||||||
//
|
//
|
||||||
// PackagePool stores all the package files, deduplicating them.
|
// PackagePool stores all the package files, deduplicating them.
|
||||||
type PackagePool interface {
|
type PackagePool interface {
|
||||||
// Verify checks whether file exists in the pool and fills back checksum info
|
// Path returns full path to package file in pool given any name and hash of file contents
|
||||||
//
|
Path(filename string, hashMD5 string) (string, error)
|
||||||
// if poolPath is empty, poolPath is generated automatically based on checksum info (if available)
|
// RelativePath returns path relative to pool's root for package files given MD5 and original filename
|
||||||
// in any case, if function returns true, it also fills back checksums with complete information about the file in the pool
|
RelativePath(filename string, hashMD5 string) (string, error)
|
||||||
Verify(poolPath, basename string, checksums *utils.ChecksumInfo, checksumStorage ChecksumStorage) (string, bool, error)
|
|
||||||
// Import copies file into package pool
|
|
||||||
//
|
|
||||||
// - srcPath is full path to source file as it is now
|
|
||||||
// - basename is desired human-readable name (canonical filename)
|
|
||||||
// - checksums are used to calculate file placement
|
|
||||||
// - move indicates whether srcPath can be removed
|
|
||||||
Import(srcPath, basename string, checksums *utils.ChecksumInfo, move bool, storage ChecksumStorage) (path string, err error)
|
|
||||||
// LegacyPath returns legacy (pre 1.1) path to package file (relative to root)
|
|
||||||
LegacyPath(filename string, checksums *utils.ChecksumInfo) (string, error)
|
|
||||||
// Stat returns Unix stat(2) info
|
|
||||||
Stat(path string) (os.FileInfo, error)
|
|
||||||
// Open returns ReadSeekerCloser to access the file
|
|
||||||
Open(path string) (ReadSeekerCloser, error)
|
|
||||||
// FilepathList returns file paths of all the files in the pool
|
// FilepathList returns file paths of all the files in the pool
|
||||||
FilepathList(progress Progress) ([]string, error)
|
FilepathList(progress Progress) ([]string, error)
|
||||||
// Remove deletes file in package pool returns its size
|
// Remove deletes file in package pool returns its size
|
||||||
Remove(path string) (size int64, err error)
|
Remove(path string) (size int64, err error)
|
||||||
}
|
// Import copies file into package pool
|
||||||
|
Import(path string, hashMD5 string) error
|
||||||
// LocalPackagePool is implemented by PackagePools residing on the same filesystem
|
|
||||||
type LocalPackagePool interface {
|
|
||||||
// GenerateTempPath generates temporary path for download (which is fast to import into package pool later on)
|
|
||||||
GenerateTempPath(filename string) (string, error)
|
|
||||||
// Link generates hardlink to destination path
|
|
||||||
Link(path, dstPath string) error
|
|
||||||
// Symlink generates symlink to destination path
|
|
||||||
Symlink(path, dstPath string) error
|
|
||||||
// FullPath generates full path to the file in pool
|
|
||||||
//
|
|
||||||
// Please use with care: it's not supposed to be used to access files
|
|
||||||
FullPath(path string) string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublishedStorage is abstraction of filesystem storing all published repositories
|
// PublishedStorage is abstraction of filesystem storing all published repositories
|
||||||
@@ -69,23 +35,15 @@ type PublishedStorage interface {
|
|||||||
// Remove removes single file under public path
|
// Remove removes single file under public path
|
||||||
Remove(path string) error
|
Remove(path string) error
|
||||||
// LinkFromPool links package file from pool to dist's pool location
|
// LinkFromPool links package file from pool to dist's pool location
|
||||||
LinkFromPool(publishedDirectory, baseName string, sourcePool PackagePool, sourcePath string, sourceChecksums utils.ChecksumInfo, force bool) error
|
LinkFromPool(publishedDirectory string, sourcePool PackagePool, sourcePath, sourceMD5 string, force bool) error
|
||||||
// Filelist returns list of files under prefix
|
// Filelist returns list of files under prefix
|
||||||
Filelist(prefix string) ([]string, error)
|
Filelist(prefix string) ([]string, error)
|
||||||
// RenameFile renames (moves) file
|
// RenameFile renames (moves) file
|
||||||
RenameFile(oldName, newName string) error
|
RenameFile(oldName, newName string) error
|
||||||
// SymLink creates a symbolic link, which can be read with ReadLink
|
|
||||||
SymLink(src string, dst string) error
|
|
||||||
// HardLink creates a hardlink of a file
|
|
||||||
HardLink(src string, dst string) error
|
|
||||||
// FileExists returns true if path exists
|
|
||||||
FileExists(path string) (bool, error)
|
|
||||||
// ReadLink returns the symbolic link pointed to by path
|
|
||||||
ReadLink(path string) (string, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileSystemPublishedStorage is published storage on filesystem
|
// LocalPublishedStorage is published storage on local filesystem
|
||||||
type FileSystemPublishedStorage interface {
|
type LocalPublishedStorage interface {
|
||||||
// PublicPath returns root of public part
|
// PublicPath returns root of public part
|
||||||
PublicPath() string
|
PublicPath() string
|
||||||
}
|
}
|
||||||
@@ -118,24 +76,23 @@ type Progress interface {
|
|||||||
Printf(msg string, a ...interface{})
|
Printf(msg string, a ...interface{})
|
||||||
// ColoredPrintf does printf in colored way + newline
|
// ColoredPrintf does printf in colored way + newline
|
||||||
ColoredPrintf(msg string, a ...interface{})
|
ColoredPrintf(msg string, a ...interface{})
|
||||||
// PrintfStdErr does printf but in safe manner to stderr
|
|
||||||
PrintfStdErr(msg string, a ...interface{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Downloader is parallel HTTP fetcher
|
// Downloader is parallel HTTP fetcher
|
||||||
type Downloader interface {
|
type Downloader interface {
|
||||||
// Download starts new download task
|
// Download starts new download task
|
||||||
Download(ctx context.Context, url string, destination string) 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(ctx context.Context, url string, destination string, expected *utils.ChecksumInfo, ignoreMismatch bool, maxTries int) error
|
DownloadWithChecksum(url string, destination string, result chan<- error, expected utils.ChecksumInfo, ignoreMismatch bool, maxTries int)
|
||||||
|
// Pause pauses task processing
|
||||||
|
Pause()
|
||||||
|
// Resume resumes task processing
|
||||||
|
Resume()
|
||||||
|
// Shutdown stops downloader after current tasks are finished,
|
||||||
|
// but doesn't process rest of queue
|
||||||
|
Shutdown()
|
||||||
|
// Abort stops downloader without waiting for shutdown
|
||||||
|
Abort()
|
||||||
// GetProgress returns Progress object
|
// GetProgress returns Progress object
|
||||||
GetProgress() Progress
|
GetProgress() Progress
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChecksumStorage is stores checksums in some (persistent) storage
|
|
||||||
type ChecksumStorage interface {
|
|
||||||
// Get finds checksums in DB by path
|
|
||||||
Get(path string) (*utils.ChecksumInfo, error)
|
|
||||||
// Update adds or updates information about checksum in DB
|
|
||||||
Update(path string, c *utils.ChecksumInfo) error
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-7
@@ -7,9 +7,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/api"
|
"github.com/smira/aptly/api"
|
||||||
"github.com/aptly-dev/aptly/systemd/activation"
|
"github.com/smira/aptly/systemd/activation"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -59,14 +59,11 @@ func aptlyAPIServe(cmd *commander.Command, args []string) error {
|
|||||||
if err == nil && listenURL.Scheme == "unix" {
|
if err == nil && listenURL.Scheme == "unix" {
|
||||||
file := listenURL.Path
|
file := listenURL.Path
|
||||||
os.Remove(file)
|
os.Remove(file)
|
||||||
|
listener, err := net.Listen("unix", file)
|
||||||
var listener net.Listener
|
|
||||||
listener, err = net.Listen("unix", file)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to listen on: %s\n%s", file, err)
|
return fmt.Errorf("failed to listen on: %s\n%s", file, err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
|
|
||||||
err = http.Serve(listener, api.Router(context))
|
err = http.Serve(listener, 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)
|
||||||
|
|||||||
+16
-21
@@ -8,18 +8,12 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Various command flags/UI things
|
|
||||||
const (
|
|
||||||
Yes = "yes"
|
|
||||||
No = "no"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListPackagesRefList shows list of packages in PackageRefList
|
// ListPackagesRefList shows list of packages in PackageRefList
|
||||||
func ListPackagesRefList(reflist *deb.PackageRefList) (err error) {
|
func ListPackagesRefList(reflist *deb.PackageRefList) (err error) {
|
||||||
fmt.Printf("Packages:\n")
|
fmt.Printf("Packages:\n")
|
||||||
@@ -28,22 +22,26 @@ func ListPackagesRefList(reflist *deb.PackageRefList) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := deb.NewPackageListFromRefList(reflist, context.CollectionFactory().PackageCollection(), context.Progress())
|
err = reflist.ForEach(func(key []byte) error {
|
||||||
|
p, err2 := context.CollectionFactory().PackageCollection().ByKey(key)
|
||||||
|
if err2 != nil {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", p)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load packages: %s", err)
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return PrintPackageList(list, "", " ")
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintPackageList shows package list with specified format or default representation
|
// PrintPackageList shows package list with specified format or default representation
|
||||||
func PrintPackageList(result *deb.PackageList, format, prefix string) error {
|
func PrintPackageList(result *deb.PackageList, format string) error {
|
||||||
result.PrepareIndex()
|
|
||||||
|
|
||||||
if format == "" {
|
if format == "" {
|
||||||
return result.ForEachIndexed(func(p *deb.Package) error {
|
return result.ForEach(func(p *deb.Package) error {
|
||||||
context.Progress().Printf(prefix+"%s\n", p)
|
context.Progress().Printf("%s\n", p)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -53,13 +51,13 @@ func PrintPackageList(result *deb.PackageList, format, prefix string) error {
|
|||||||
return fmt.Errorf("error parsing -format template: %s", err)
|
return fmt.Errorf("error parsing -format template: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.ForEachIndexed(func(p *deb.Package) error {
|
return result.ForEach(func(p *deb.Package) error {
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
err = formatTemplate.Execute(b, p.ExtendedStanza())
|
err = formatTemplate.Execute(b, p.ExtendedStanza())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error applying template: %s", err)
|
return fmt.Errorf("error applying template: %s", err)
|
||||||
}
|
}
|
||||||
context.Progress().Printf(prefix+"%s\n", b.String())
|
context.Progress().Printf("%s\n", b.String())
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,15 +109,12 @@ package environment to new version.`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flag.Int("db-open-attempts", 10, "number of attempts to open DB if it's locked by other instance")
|
|
||||||
cmd.Flag.Bool("dep-follow-suggests", false, "when processing dependencies, follow Suggests")
|
cmd.Flag.Bool("dep-follow-suggests", false, "when processing dependencies, follow Suggests")
|
||||||
cmd.Flag.Bool("dep-follow-source", false, "when processing dependencies, follow from binary to Source packages")
|
cmd.Flag.Bool("dep-follow-source", false, "when processing dependencies, follow from binary to Source packages")
|
||||||
cmd.Flag.Bool("dep-follow-recommends", false, "when processing dependencies, follow Recommends")
|
cmd.Flag.Bool("dep-follow-recommends", false, "when processing dependencies, follow Recommends")
|
||||||
cmd.Flag.Bool("dep-follow-all-variants", false, "when processing dependencies, follow a & b if dependency is 'a|b'")
|
cmd.Flag.Bool("dep-follow-all-variants", false, "when processing dependencies, follow a & b if dependency is 'a|b'")
|
||||||
cmd.Flag.Bool("dep-verbose-resolve", false, "when processing dependencies, print detailed logs")
|
|
||||||
cmd.Flag.String("architectures", "", "list of architectures to consider during (comma-separated), default to all available")
|
cmd.Flag.String("architectures", "", "list of architectures to consider during (comma-separated), default to all available")
|
||||||
cmd.Flag.String("config", "", "location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)")
|
cmd.Flag.String("config", "", "location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)")
|
||||||
cmd.Flag.String("gpg-provider", "", "PGP implementation (\"gpg\" for external gpg or \"internal\" for Go internal implementation)")
|
|
||||||
|
|
||||||
if aptly.EnableDebug {
|
if aptly.EnableDebug {
|
||||||
cmd.Flag.String("cpuprofile", "", "write cpu profile to file")
|
cmd.Flag.String("cpuprofile", "", "write cpu profile to file")
|
||||||
|
|||||||
+1
-6
@@ -1,7 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ctx "github.com/aptly-dev/aptly/context"
|
ctx "github.com/smira/aptly/context"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,8 +29,3 @@ func InitContext(flags *flag.FlagSet) error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContext gives access to the context
|
|
||||||
func GetContext() *ctx.AptlyContext {
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|||||||
+15
-15
@@ -5,8 +5,8 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,9 +37,9 @@ func aptlyDbCleanup(cmd *commander.Command, args []string) error {
|
|||||||
context.Progress().ColoredPrintf("- @{g}%s@|", repo.Name)
|
context.Progress().ColoredPrintf("- @{g}%s@|", repo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
err := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
if repo.RefList() != nil {
|
if repo.RefList() != nil {
|
||||||
existingPackageRefs = existingPackageRefs.Merge(repo.RefList(), false, true)
|
existingPackageRefs = existingPackageRefs.Merge(repo.RefList(), false, true)
|
||||||
@@ -67,9 +67,9 @@ func aptlyDbCleanup(cmd *commander.Command, args []string) error {
|
|||||||
context.Progress().ColoredPrintf("- @{g}%s@|", repo.Name)
|
context.Progress().ColoredPrintf("- @{g}%s@|", repo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
err := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.RefList() != nil {
|
if repo.RefList() != nil {
|
||||||
@@ -98,9 +98,9 @@ func aptlyDbCleanup(cmd *commander.Command, args []string) error {
|
|||||||
context.Progress().ColoredPrintf("- @{g}%s@|", snapshot.Name)
|
context.Progress().ColoredPrintf("- @{g}%s@|", snapshot.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
err := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
existingPackageRefs = existingPackageRefs.Merge(snapshot.RefList(), false, true)
|
existingPackageRefs = existingPackageRefs.Merge(snapshot.RefList(), false, true)
|
||||||
@@ -125,12 +125,12 @@ func aptlyDbCleanup(cmd *commander.Command, args []string) error {
|
|||||||
if verbose {
|
if verbose {
|
||||||
context.Progress().ColoredPrintf("- @{g}%s:%s/%s{|}", published.Storage, published.Prefix, published.Distribution)
|
context.Progress().ColoredPrintf("- @{g}%s:%s/%s{|}", published.Storage, published.Prefix, published.Distribution)
|
||||||
}
|
}
|
||||||
if published.SourceKind != deb.SourceLocalRepo {
|
if published.SourceKind != "local" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
e := context.CollectionFactory().PublishedRepoCollection().LoadComplete(published, context.CollectionFactory())
|
err := context.CollectionFactory().PublishedRepoCollection().LoadComplete(published, context.CollectionFactory())
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, component := range published.Components() {
|
for _, component := range published.Components() {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -12,8 +12,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -3,19 +3,19 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getVerifier(flags *flag.FlagSet) (pgp.Verifier, error) {
|
func getVerifier(flags *flag.FlagSet) (utils.Verifier, error) {
|
||||||
if LookupOption(context.Config().GpgDisableVerify, flags, "ignore-signatures") {
|
if LookupOption(context.Config().GpgDisableVerify, flags, "ignore-signatures") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
keyRings := flags.Lookup("keyring").Value.Get().([]string)
|
keyRings := flags.Lookup("keyring").Value.Get().([]string)
|
||||||
|
|
||||||
verifier := context.GetVerifier()
|
verifier := &utils.GpgVerifier{}
|
||||||
for _, keyRing := range keyRings {
|
for _, keyRing := range keyRings {
|
||||||
verifier.AddKeyring(keyRing)
|
verifier.AddKeyring(keyRing)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-19
@@ -3,8 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/aptly-dev/aptly/query"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -26,7 +25,6 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to edit: %s", err)
|
return fmt.Errorf("unable to edit: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchMirror := false
|
|
||||||
context.Flags().Visit(func(flag *flag.Flag) {
|
context.Flags().Visit(func(flag *flag.Flag) {
|
||||||
switch flag.Name {
|
switch flag.Name {
|
||||||
case "filter":
|
case "filter":
|
||||||
@@ -37,9 +35,6 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error {
|
|||||||
repo.DownloadSources = flag.Value.Get().(bool)
|
repo.DownloadSources = flag.Value.Get().(bool)
|
||||||
case "with-udebs":
|
case "with-udebs":
|
||||||
repo.DownloadUdebs = flag.Value.Get().(bool)
|
repo.DownloadUdebs = flag.Value.Get().(bool)
|
||||||
case "archive-url":
|
|
||||||
repo.SetArchiveRoot(flag.Value.String())
|
|
||||||
fetchMirror = true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -56,17 +51,8 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
if context.GlobalFlags().Lookup("architectures").Value.String() != "" {
|
if context.GlobalFlags().Lookup("architectures").Value.String() != "" {
|
||||||
repo.Architectures = context.ArchitecturesList()
|
repo.Architectures = context.ArchitecturesList()
|
||||||
fetchMirror = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if fetchMirror {
|
err = repo.Fetch(context.Downloader(), nil)
|
||||||
var verifier pgp.Verifier
|
|
||||||
verifier, err = getVerifier(context.Flags())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to initialize GPG verifier: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = repo.Fetch(context.Downloader(), verifier)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to edit: %s", err)
|
return fmt.Errorf("unable to edit: %s", err)
|
||||||
}
|
}
|
||||||
@@ -97,13 +83,10 @@ Example:
|
|||||||
Flag: *flag.NewFlagSet("aptly-mirror-edit", flag.ExitOnError),
|
Flag: *flag.NewFlagSet("aptly-mirror-edit", flag.ExitOnError),
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flag.String("archive-url", "", "archive url is the root of archive")
|
|
||||||
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("ignore-signatures", false, "disable verification of Release file signatures")
|
|
||||||
cmd.Flag.Bool("with-sources", false, "download source packages in addition to binary packages")
|
cmd.Flag.Bool("with-sources", false, "download source packages in addition to binary packages")
|
||||||
cmd.Flag.Bool("with-udebs", false, "download .udeb packages (Debian installer support)")
|
cmd.Flag.Bool("with-udebs", false, "download .udeb packages (Debian installer support)")
|
||||||
cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -37,21 +37,21 @@ func aptlyMirrorShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("Distribution: %s\n", repo.Distribution)
|
fmt.Printf("Distribution: %s\n", repo.Distribution)
|
||||||
fmt.Printf("Components: %s\n", strings.Join(repo.Components, ", "))
|
fmt.Printf("Components: %s\n", strings.Join(repo.Components, ", "))
|
||||||
fmt.Printf("Architectures: %s\n", strings.Join(repo.Architectures, ", "))
|
fmt.Printf("Architectures: %s\n", strings.Join(repo.Architectures, ", "))
|
||||||
downloadSources := No
|
downloadSources := "no"
|
||||||
if repo.DownloadSources {
|
if repo.DownloadSources {
|
||||||
downloadSources = Yes
|
downloadSources = "yes"
|
||||||
}
|
}
|
||||||
fmt.Printf("Download Sources: %s\n", downloadSources)
|
fmt.Printf("Download Sources: %s\n", downloadSources)
|
||||||
downloadUdebs := No
|
downloadUdebs := "no"
|
||||||
if repo.DownloadUdebs {
|
if repo.DownloadUdebs {
|
||||||
downloadUdebs = Yes
|
downloadUdebs = "yes"
|
||||||
}
|
}
|
||||||
fmt.Printf("Download .udebs: %s\n", downloadUdebs)
|
fmt.Printf("Download .udebs: %s\n", downloadUdebs)
|
||||||
if repo.Filter != "" {
|
if repo.Filter != "" {
|
||||||
fmt.Printf("Filter: %s\n", repo.Filter)
|
fmt.Printf("Filter: %s\n", repo.Filter)
|
||||||
filterWithDeps := No
|
filterWithDeps := "no"
|
||||||
if repo.FilterWithDeps {
|
if repo.FilterWithDeps {
|
||||||
filterWithDeps = Yes
|
filterWithDeps = "yes"
|
||||||
}
|
}
|
||||||
fmt.Printf("Filter With Deps: %s\n", filterWithDeps)
|
fmt.Printf("Filter With Deps: %s\n", filterWithDeps)
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-117
@@ -2,13 +2,13 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -69,7 +69,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var oldLen, newLen int
|
var oldLen, newLen int
|
||||||
oldLen, newLen, err = repo.ApplyFilter(context.DependencyOptions(), filterQuery, context.Progress())
|
oldLen, newLen, err = repo.ApplyFilter(context.DependencyOptions(), filterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
@@ -81,12 +81,8 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
queue []deb.PackageDownloadTask
|
queue []deb.PackageDownloadTask
|
||||||
)
|
)
|
||||||
|
|
||||||
skipExistingPackages := context.Flags().Lookup("skip-existing-packages").Value.Get().(bool)
|
|
||||||
|
|
||||||
context.Progress().Printf("Building download queue...\n")
|
context.Progress().Printf("Building download queue...\n")
|
||||||
queue, downloadSize, err = repo.BuildDownloadQueue(context.PackagePool(), context.CollectionFactory().PackageCollection(),
|
queue, downloadSize, err = repo.BuildDownloadQueue(context.PackagePool())
|
||||||
context.CollectionFactory().ChecksumCollection(), skipExistingPackages)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
@@ -111,7 +107,9 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.GoContextHandleSignals()
|
// Catch ^C
|
||||||
|
sigch := make(chan os.Signal)
|
||||||
|
signal.Notify(sigch, os.Interrupt)
|
||||||
|
|
||||||
count := len(queue)
|
count := len(queue)
|
||||||
context.Progress().Printf("Download queue: %d items (%s)\n", count, utils.HumanBytes(downloadSize))
|
context.Progress().Printf("Download queue: %d items (%s)\n", count, utils.HumanBytes(downloadSize))
|
||||||
@@ -119,124 +117,48 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
// Download from the queue
|
// Download from the queue
|
||||||
context.Progress().InitBar(downloadSize, true)
|
context.Progress().InitBar(downloadSize, true)
|
||||||
|
|
||||||
downloadQueue := make(chan int)
|
// Download all package files
|
||||||
|
ch := make(chan error, count)
|
||||||
|
|
||||||
var (
|
// In separate goroutine (to avoid blocking main), push queue to downloader
|
||||||
errors []string
|
go func() {
|
||||||
errLock sync.Mutex
|
for _, task := range queue {
|
||||||
)
|
context.Downloader().DownloadWithChecksum(repo.PackageURL(task.RepoURI).String(), task.DestinationPath, ch, task.Checksums, ignoreMismatch, maxTries)
|
||||||
|
}
|
||||||
|
|
||||||
pushError := func(err error) {
|
// We don't need queue after this point
|
||||||
errLock.Lock()
|
queue = nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for all downloads to finish
|
||||||
|
var errors []string
|
||||||
|
|
||||||
|
for count > 0 {
|
||||||
|
select {
|
||||||
|
case <-sigch:
|
||||||
|
signal.Stop(sigch)
|
||||||
|
return fmt.Errorf("unable to update: interrupted")
|
||||||
|
case err = <-ch:
|
||||||
|
if err != nil {
|
||||||
errors = append(errors, err.Error())
|
errors = append(errors, err.Error())
|
||||||
errLock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
count--
|
||||||
go func() {
|
|
||||||
for idx := range queue {
|
|
||||||
select {
|
|
||||||
case downloadQueue <- idx:
|
|
||||||
case <-context.Done():
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(downloadQueue)
|
|
||||||
}()
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
for i := 0; i < context.Config().DownloadConcurrency; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case idx, ok := <-downloadQueue:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
task := &queue[idx]
|
|
||||||
|
|
||||||
var e error
|
|
||||||
|
|
||||||
// provision download location
|
|
||||||
task.TempDownPath, e = context.PackagePool().(aptly.LocalPackagePool).GenerateTempPath(task.File.Filename)
|
|
||||||
if e != nil {
|
|
||||||
pushError(e)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// download file...
|
|
||||||
e = context.Downloader().DownloadWithChecksum(
|
|
||||||
context,
|
|
||||||
repo.PackageURL(task.File.DownloadURL()).String(),
|
|
||||||
task.TempDownPath,
|
|
||||||
&task.File.Checksums,
|
|
||||||
ignoreMismatch,
|
|
||||||
maxTries)
|
|
||||||
if e != nil {
|
|
||||||
pushError(e)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
task.Done = true
|
|
||||||
case <-context.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all download goroutines to finish
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
context.Progress().ShutdownBar()
|
context.Progress().ShutdownBar()
|
||||||
|
signal.Stop(sigch)
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return fmt.Errorf("unable to update: download errors:\n %s", strings.Join(errors, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
err = context.ReOpenDatabase()
|
err = context.ReOpenDatabase()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import downloaded files
|
repo.FinalizeDownload()
|
||||||
context.Progress().InitBar(int64(len(queue)), false)
|
|
||||||
|
|
||||||
for idx := range queue {
|
|
||||||
context.Progress().AddBar(1)
|
|
||||||
|
|
||||||
task := &queue[idx]
|
|
||||||
|
|
||||||
if !task.Done {
|
|
||||||
// download not finished yet
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// and import it back to the pool
|
|
||||||
task.File.PoolPath, err = context.PackagePool().Import(task.TempDownPath, task.File.Filename, &task.File.Checksums, true, context.CollectionFactory().ChecksumCollection())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to import file: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// update "attached" files if any
|
|
||||||
for _, additionalTask := range task.Additional {
|
|
||||||
additionalTask.File.PoolPath = task.File.PoolPath
|
|
||||||
additionalTask.File.Checksums = task.File.Checksums
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Progress().ShutdownBar()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-context.Done():
|
|
||||||
return fmt.Errorf("unable to update: interrupted")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return fmt.Errorf("unable to update: download errors:\n %s", strings.Join(errors, "\n "))
|
|
||||||
}
|
|
||||||
|
|
||||||
repo.FinalizeDownload(context.CollectionFactory(), context.Progress())
|
|
||||||
err = context.CollectionFactory().RemoteRepoCollection().Update(repo)
|
err = context.CollectionFactory().RemoteRepoCollection().Update(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
@@ -266,7 +188,6 @@ Example:
|
|||||||
cmd.Flag.Bool("force", false, "force update mirror even if it is locked by another process")
|
cmd.Flag.Bool("force", false, "force update mirror even if it is locked by another process")
|
||||||
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.Bool("skip-existing-packages", false, "do not check file existence for packages listed in the internal database of the mirror")
|
|
||||||
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.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)")
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -35,7 +35,7 @@ func aptlyPackageSearch(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
format := context.Flags().Lookup("format").Value.String()
|
format := context.Flags().Lookup("format").Value.String()
|
||||||
PrintPackageList(result, format, "")
|
PrintPackageList(result, format)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-21
@@ -5,18 +5,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/aptly-dev/aptly/query"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printReferencesTo(p *deb.Package) (err error) {
|
func printReferencesTo(p *deb.Package) (err error) {
|
||||||
err = context.CollectionFactory().RemoteRepoCollection().ForEach(func(repo *deb.RemoteRepo) error {
|
err = context.CollectionFactory().RemoteRepoCollection().ForEach(func(repo *deb.RemoteRepo) error {
|
||||||
e := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
err := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
if repo.RefList() != nil {
|
if repo.RefList() != nil {
|
||||||
if repo.RefList().Has(p) {
|
if repo.RefList().Has(p) {
|
||||||
@@ -30,9 +29,9 @@ func printReferencesTo(p *deb.Package) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
|
err = context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
|
||||||
e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
err := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
if repo.RefList() != nil {
|
if repo.RefList() != nil {
|
||||||
if repo.RefList().Has(p) {
|
if repo.RefList().Has(p) {
|
||||||
@@ -46,17 +45,20 @@ func printReferencesTo(p *deb.Package) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
err = context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
||||||
e := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
err := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
if snapshot.RefList().Has(p) {
|
if snapshot.RefList().Has(p) {
|
||||||
fmt.Printf(" snapshot %s\n", snapshot)
|
fmt.Printf(" snapshot %s\n", snapshot)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func aptlyPackageShow(cmd *commander.Command, args []string) error {
|
func aptlyPackageShow(cmd *commander.Command, args []string) error {
|
||||||
@@ -85,18 +87,11 @@ func aptlyPackageShow(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
if withFiles {
|
if withFiles {
|
||||||
fmt.Printf("Files in the pool:\n")
|
fmt.Printf("Files in the pool:\n")
|
||||||
packagePool := context.PackagePool()
|
|
||||||
for _, f := range p.Files() {
|
for _, f := range p.Files() {
|
||||||
var path string
|
path, err := context.PackagePool().Path(f.Filename, f.Checksums.MD5)
|
||||||
path, err = f.GetPoolPath(packagePool)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pp, ok := packagePool.(aptly.LocalPackagePool); ok {
|
|
||||||
path = pp.FullPath(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf(" %s\n", path)
|
fmt.Printf(" %s\n", path)
|
||||||
}
|
}
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|||||||
+3
-3
@@ -1,17 +1,17 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getSigner(flags *flag.FlagSet) (pgp.Signer, error) {
|
func getSigner(flags *flag.FlagSet) (utils.Signer, error) {
|
||||||
if LookupOption(context.Config().GpgDisableSign, flags, "skip-signing") {
|
if LookupOption(context.Config().GpgDisableSign, flags, "skip-signing") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
signer := context.GetSigner()
|
signer := &utils.GpgSigner{}
|
||||||
signer.SetKey(flags.Lookup("gpg-key").Value.String())
|
signer.SetKey(flags.Lookup("gpg-key").Value.String())
|
||||||
signer.SetKeyRing(flags.Lookup("keyring").Value.String(), flags.Lookup("secret-keyring").Value.String())
|
signer.SetKeyRing(flags.Lookup("keyring").Value.String(), flags.Lookup("secret-keyring").Value.String())
|
||||||
signer.SetPassphrase(flags.Lookup("passphrase").Value.String(), flags.Lookup("passphrase-file").Value.String())
|
signer.SetPassphrase(flags.Lookup("passphrase").Value.String(), flags.Lookup("passphrase-file").Value.String())
|
||||||
|
|||||||
+2
-5
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,9 +24,7 @@ func aptlyPublishDrop(cmd *commander.Command, args []string) error {
|
|||||||
storage, prefix := deb.ParsePrefix(param)
|
storage, prefix := deb.ParsePrefix(param)
|
||||||
|
|
||||||
err = context.CollectionFactory().PublishedRepoCollection().Remove(context, storage, prefix, distribution,
|
err = context.CollectionFactory().PublishedRepoCollection().Remove(context, storage, prefix, distribution,
|
||||||
context.CollectionFactory(), context.Progress(),
|
context.CollectionFactory(), context.Progress(), context.Flags().Lookup("force-drop").Value.Get().(bool))
|
||||||
context.Flags().Lookup("force-drop").Value.Get().(bool),
|
|
||||||
context.Flags().Lookup("skip-cleanup").Value.Get().(bool))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to remove: %s", err)
|
return fmt.Errorf("unable to remove: %s", err)
|
||||||
}
|
}
|
||||||
@@ -52,7 +50,6 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flag.Bool("force-drop", false, "remove published repository even if some files could not be cleaned up")
|
cmd.Flag.Bool("force-drop", false, "remove published repository even if some files could not be cleaned up")
|
||||||
cmd.Flag.Bool("skip-cleanup", false, "don't remove unreferenced files in prefix/component")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@ func aptlyPublishList(cmd *commander.Command, args []string) error {
|
|||||||
published := make([]string, 0, context.CollectionFactory().PublishedRepoCollection().Len())
|
published := make([]string, 0, context.CollectionFactory().PublishedRepoCollection().Len())
|
||||||
|
|
||||||
err = context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
err = context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
||||||
e := context.CollectionFactory().PublishedRepoCollection().LoadComplete(repo, context.CollectionFactory())
|
err := context.CollectionFactory().PublishedRepoCollection().LoadComplete(repo, context.CollectionFactory())
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw {
|
if raw {
|
||||||
|
|||||||
@@ -43,11 +43,8 @@ Example:
|
|||||||
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
||||||
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
||||||
cmd.Flag.String("origin", "", "origin name to publish")
|
cmd.Flag.String("origin", "", "origin name to publish")
|
||||||
cmd.Flag.String("notautomatic", "", "set value for NotAutomatic field")
|
|
||||||
cmd.Flag.String("butautomaticupgrades", "", "set value for ButAutomaticUpgrades field")
|
|
||||||
cmd.Flag.String("label", "", "label to publish")
|
cmd.Flag.String("label", "", "label to publish")
|
||||||
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
||||||
cmd.Flag.Bool("acquire-by-hash", false, "provide index files by hash")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,15 +41,15 @@ func aptlyPublishShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("Sources:\n")
|
fmt.Printf("Sources:\n")
|
||||||
for component, sourceID := range repo.Sources {
|
for component, sourceID := range repo.Sources {
|
||||||
var name string
|
var name string
|
||||||
if repo.SourceKind == deb.SourceSnapshot {
|
if repo.SourceKind == "snapshot" {
|
||||||
source, e := context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
|
source, err := context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name = source.Name
|
name = source.Name
|
||||||
} else if repo.SourceKind == deb.SourceLocalRepo {
|
} else if repo.SourceKind == "local" {
|
||||||
source, e := context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
|
source, err := context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name = source.Name
|
name = source.Name
|
||||||
|
|||||||
+9
-27
@@ -4,9 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -35,7 +35,7 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
message string
|
message string
|
||||||
)
|
)
|
||||||
|
|
||||||
if cmd.Name() == "snapshot" { // nolint: goconst
|
if cmd.Name() == "snapshot" {
|
||||||
var (
|
var (
|
||||||
snapshot *deb.Snapshot
|
snapshot *deb.Snapshot
|
||||||
emptyWarning = false
|
emptyWarning = false
|
||||||
@@ -71,7 +71,7 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
if emptyWarning {
|
if emptyWarning {
|
||||||
context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n")
|
context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n")
|
||||||
}
|
}
|
||||||
} else if cmd.Name() == "repo" { // nolint: goconst
|
} else if cmd.Name() == "repo" {
|
||||||
var (
|
var (
|
||||||
localRepo *deb.LocalRepo
|
localRepo *deb.LocalRepo
|
||||||
emptyWarning = false
|
emptyWarning = false
|
||||||
@@ -112,23 +112,12 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
distribution := context.Flags().Lookup("distribution").Value.String()
|
distribution := context.Flags().Lookup("distribution").Value.String()
|
||||||
origin := context.Flags().Lookup("origin").Value.String()
|
|
||||||
notAutomatic := context.Flags().Lookup("notautomatic").Value.String()
|
|
||||||
butAutomaticUpgrades := context.Flags().Lookup("butautomaticupgrades").Value.String()
|
|
||||||
|
|
||||||
published, err := deb.NewPublishedRepo(storage, prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory())
|
published, err := deb.NewPublishedRepo(storage, prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to publish: %s", err)
|
return fmt.Errorf("unable to publish: %s", err)
|
||||||
}
|
}
|
||||||
if origin != "" {
|
published.Origin = context.Flags().Lookup("origin").Value.String()
|
||||||
published.Origin = origin
|
|
||||||
}
|
|
||||||
if notAutomatic != "" {
|
|
||||||
published.NotAutomatic = notAutomatic
|
|
||||||
}
|
|
||||||
if butAutomaticUpgrades != "" {
|
|
||||||
published.ButAutomaticUpgrades = butAutomaticUpgrades
|
|
||||||
}
|
|
||||||
published.Label = context.Flags().Lookup("label").Value.String()
|
published.Label = context.Flags().Lookup("label").Value.String()
|
||||||
|
|
||||||
published.SkipContents = context.Config().SkipContentsPublishing
|
published.SkipContents = context.Config().SkipContentsPublishing
|
||||||
@@ -137,10 +126,6 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
published.SkipContents = context.Flags().Lookup("skip-contents").Value.Get().(bool)
|
published.SkipContents = context.Flags().Lookup("skip-contents").Value.Get().(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.Flags().IsSet("acquire-by-hash") {
|
|
||||||
published.AcquireByHash = context.Flags().Lookup("acquire-by-hash").Value.Get().(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
duplicate := context.CollectionFactory().PublishedRepoCollection().CheckDuplicate(published)
|
duplicate := context.CollectionFactory().PublishedRepoCollection().CheckDuplicate(published)
|
||||||
if duplicate != nil {
|
if duplicate != nil {
|
||||||
context.CollectionFactory().PublishedRepoCollection().LoadComplete(duplicate, context.CollectionFactory())
|
context.CollectionFactory().PublishedRepoCollection().LoadComplete(duplicate, context.CollectionFactory())
|
||||||
@@ -178,14 +163,14 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
context.Progress().Printf("\n%s been successfully published.\n", message)
|
context.Progress().Printf("\n%s been successfully published.\n", message)
|
||||||
|
|
||||||
if localStorage, ok := context.GetPublishedStorage(storage).(aptly.FileSystemPublishedStorage); ok {
|
if localStorage, ok := context.GetPublishedStorage(storage).(aptly.LocalPublishedStorage); ok {
|
||||||
context.Progress().Printf("Please setup your webserver to serve directory '%s' with autoindexing.\n",
|
context.Progress().Printf("Please setup your webserver to serve directory '%s' with autoindexing.\n",
|
||||||
localStorage.PublicPath())
|
localStorage.PublicPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Progress().Printf("Now you can add following line to apt sources:\n")
|
context.Progress().Printf("Now you can add following line to apt sources:\n")
|
||||||
context.Progress().Printf(" deb http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
|
context.Progress().Printf(" deb http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
|
||||||
if utils.StrSliceHasItem(published.Architectures, deb.ArchitectureSource) {
|
if utils.StrSliceHasItem(published.Architectures, "source") {
|
||||||
context.Progress().Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
|
context.Progress().Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
|
||||||
}
|
}
|
||||||
context.Progress().Printf("Don't forget to add your GPG key to apt with apt-key.\n")
|
context.Progress().Printf("Don't forget to add your GPG key to apt with apt-key.\n")
|
||||||
@@ -226,12 +211,9 @@ Example:
|
|||||||
cmd.Flag.Bool("batch", false, "run GPG with detached tty")
|
cmd.Flag.Bool("batch", false, "run GPG with detached tty")
|
||||||
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
||||||
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
||||||
cmd.Flag.String("origin", "", "overwrite origin name to publish")
|
cmd.Flag.String("origin", "", "origin name to publish")
|
||||||
cmd.Flag.String("notautomatic", "", "overwrite value for NotAutomatic field")
|
|
||||||
cmd.Flag.String("butautomaticupgrades", "", "overwrite value for ButAutomaticUpgrades field")
|
|
||||||
cmd.Flag.String("label", "", "label to publish")
|
cmd.Flag.String("label", "", "label to publish")
|
||||||
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
||||||
cmd.Flag.Bool("acquire-by-hash", false, "provide index files by hash")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -44,7 +44,7 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if published.SourceKind != deb.SourceSnapshot {
|
if published.SourceKind != "snapshot" {
|
||||||
return fmt.Errorf("unable to update: not a snapshot publish")
|
return fmt.Errorf("unable to update: not a snapshot publish")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,14 +105,11 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to save to DB: %s", err)
|
return fmt.Errorf("unable to save to DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
skipCleanup := context.Flags().Lookup("skip-cleanup").Value.Get().(bool)
|
|
||||||
if !skipCleanup {
|
|
||||||
err = context.CollectionFactory().PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components,
|
err = context.CollectionFactory().PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components,
|
||||||
context.GetPublishedStorage(storage), context.CollectionFactory(), context.Progress())
|
context.GetPublishedStorage(storage), context.CollectionFactory(), context.Progress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
context.Progress().Printf("\nPublish for snapshot %s has been successfully switched to new snapshot.\n", published.String())
|
context.Progress().Printf("\nPublish for snapshot %s has been successfully switched to new snapshot.\n", published.String())
|
||||||
|
|
||||||
@@ -154,7 +151,6 @@ This command would switch published repository (with one component) named ppa/wh
|
|||||||
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
||||||
cmd.Flag.String("component", "", "component names to update (for multi-component publishing, separate components with commas)")
|
cmd.Flag.String("component", "", "component names to update (for multi-component publishing, separate components with commas)")
|
||||||
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
||||||
cmd.Flag.Bool("skip-cleanup", false, "don't remove unreferenced files in prefix/component")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -30,7 +30,7 @@ func aptlyPublishUpdate(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if published.SourceKind != deb.SourceLocalRepo {
|
if published.SourceKind != "local" {
|
||||||
return fmt.Errorf("unable to update: not a local repository publish")
|
return fmt.Errorf("unable to update: not a local repository publish")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,14 +69,11 @@ func aptlyPublishUpdate(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to save to DB: %s", err)
|
return fmt.Errorf("unable to save to DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
skipCleanup := context.Flags().Lookup("skip-cleanup").Value.Get().(bool)
|
|
||||||
if !skipCleanup {
|
|
||||||
err = context.CollectionFactory().PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components,
|
err = context.CollectionFactory().PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components,
|
||||||
context.GetPublishedStorage(storage), context.CollectionFactory(), context.Progress())
|
context.GetPublishedStorage(storage), context.CollectionFactory(), context.Progress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
context.Progress().Printf("\nPublish for local repo %s has been successfully updated.\n", published.String())
|
context.Progress().Printf("\nPublish for local repo %s has been successfully updated.\n", published.String())
|
||||||
|
|
||||||
@@ -112,7 +109,6 @@ Example:
|
|||||||
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
|
||||||
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
|
||||||
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
|
||||||
cmd.Flag.Bool("skip-cleanup", false, "don't remove unreferenced files in prefix/component")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-11
@@ -4,9 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -20,7 +20,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
|
||||||
verifier := context.GetVerifier()
|
verifier := &utils.GpgVerifier{}
|
||||||
|
|
||||||
repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
|
repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -41,22 +41,19 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
||||||
|
|
||||||
var packageFiles, otherFiles, failedFiles []string
|
var packageFiles, failedFiles []string
|
||||||
|
|
||||||
packageFiles, otherFiles, failedFiles = deb.CollectPackageFiles(args[1:], &aptly.ConsoleResultReporter{Progress: context.Progress()})
|
packageFiles, failedFiles = deb.CollectPackageFiles(args[1:], &aptly.ConsoleResultReporter{Progress: context.Progress()})
|
||||||
|
|
||||||
var processedFiles, failedFiles2 []string
|
var processedFiles, failedFiles2 []string
|
||||||
|
|
||||||
processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
||||||
context.CollectionFactory().PackageCollection(), &aptly.ConsoleResultReporter{Progress: context.Progress()}, nil,
|
context.CollectionFactory().PackageCollection(), &aptly.ConsoleResultReporter{Progress: context.Progress()}, nil)
|
||||||
context.CollectionFactory().ChecksumCollection())
|
|
||||||
failedFiles = append(failedFiles, failedFiles2...)
|
failedFiles = append(failedFiles, failedFiles2...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to import package files: %s", err)
|
return fmt.Errorf("unable to import package files: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
processedFiles = append(processedFiles, otherFiles...)
|
|
||||||
|
|
||||||
repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))
|
repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
||||||
@@ -68,7 +65,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||||||
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
||||||
|
|
||||||
for _, file := range processedFiles {
|
for _, file := range processedFiles {
|
||||||
err = os.Remove(file)
|
err := os.Remove(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to remove file: %s", err)
|
return fmt.Errorf("unable to remove file: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,14 +3,14 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 || (len(args) == 4 && args[1] == "from" && args[2] == "snapshot")) { // nolint: goconst
|
if !(len(args) == 1 || (len(args) == 4 && args[1] == "from" && args[2] == "snapshot")) {
|
||||||
cmd.Usage()
|
cmd.Usage()
|
||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/AlekSi/pointer"
|
"github.com/AlekSi/pointer"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|||||||
+10
-16
@@ -7,10 +7,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -28,7 +28,7 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if verifier == nil {
|
if verifier == nil {
|
||||||
verifier = context.GetVerifier()
|
verifier = &utils.GpgVerifier{}
|
||||||
}
|
}
|
||||||
|
|
||||||
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
||||||
@@ -97,8 +97,7 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
context.Progress().Printf("Loading repository %s for changes file %s...\n", repoName.String(), changes.ChangesName)
|
context.Progress().Printf("Loading repository %s for changes file %s...\n", repoName.String(), changes.ChangesName)
|
||||||
|
|
||||||
var repo *deb.LocalRepo
|
repo, err := context.CollectionFactory().LocalRepoCollection().ByName(repoName.String())
|
||||||
repo, err = context.CollectionFactory().LocalRepoCollection().ByName(repoName.String())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failedFiles = append(failedFiles, path)
|
failedFiles = append(failedFiles, path)
|
||||||
reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
|
reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
|
||||||
@@ -132,13 +131,12 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to load repo: %s", err)
|
return fmt.Errorf("unable to load repo: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var list *deb.PackageList
|
list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
|
||||||
list, err = deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load packages: %s", err)
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
packageFiles, otherFiles, _ := deb.CollectPackageFiles([]string{changes.TempDir}, reporter)
|
packageFiles, _ := deb.CollectPackageFiles([]string{changes.TempDir}, reporter)
|
||||||
|
|
||||||
var restriction deb.PackageQuery
|
var restriction deb.PackageQuery
|
||||||
|
|
||||||
@@ -153,7 +151,7 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
var processedFiles2, failedFiles2 []string
|
var processedFiles2, failedFiles2 []string
|
||||||
|
|
||||||
processedFiles2, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
processedFiles2, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
|
||||||
context.CollectionFactory().PackageCollection(), reporter, restriction, context.CollectionFactory().ChecksumCollection())
|
context.CollectionFactory().PackageCollection(), reporter, restriction)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to import package files: %s", err)
|
return fmt.Errorf("unable to import package files: %s", err)
|
||||||
@@ -179,10 +177,6 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
processedFiles = append(processedFiles, filepath.Join(changes.BasePath, filepath.Base(file)))
|
processedFiles = append(processedFiles, filepath.Join(changes.BasePath, filepath.Base(file)))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range otherFiles {
|
|
||||||
processedFiles = append(processedFiles, filepath.Join(changes.BasePath, filepath.Base(file)))
|
|
||||||
}
|
|
||||||
|
|
||||||
processedFiles = append(processedFiles, path)
|
processedFiles = append(processedFiles, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +184,7 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||||||
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
||||||
|
|
||||||
for _, file := range processedFiles {
|
for _, file := range processedFiles {
|
||||||
err = os.Remove(file)
|
err := os.Remove(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to remove file: %s", err)
|
return fmt.Errorf("unable to remove file: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@ func aptlyRepoList(cmd *commander.Command, args []string) error {
|
|||||||
if raw {
|
if raw {
|
||||||
repos[i] = repo.Name
|
repos[i] = repo.Name
|
||||||
} else {
|
} else {
|
||||||
e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
err := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
repos[i] = fmt.Sprintf(" * %s (packages: %d)", repo.String(), repo.NumPackages())
|
repos[i] = fmt.Sprintf(" * %s (packages: %d)", repo.String(), repo.NumPackages())
|
||||||
|
|||||||
+10
-10
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -34,7 +34,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
srcRepo *deb.LocalRepo
|
srcRepo *deb.LocalRepo
|
||||||
)
|
)
|
||||||
|
|
||||||
if command == "copy" || command == "move" { // nolint: goconst
|
if command == "copy" || command == "move" {
|
||||||
srcRepo, err = context.CollectionFactory().LocalRepoCollection().ByName(args[0])
|
srcRepo, err = context.CollectionFactory().LocalRepoCollection().ByName(args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to %s: %s", command, err)
|
return fmt.Errorf("unable to %s: %s", command, err)
|
||||||
@@ -50,7 +50,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
srcRefList = srcRepo.RefList()
|
srcRefList = srcRepo.RefList()
|
||||||
} else if command == "import" { // nolint: goconst
|
} else if command == "import" {
|
||||||
var srcRemoteRepo *deb.RemoteRepo
|
var srcRemoteRepo *deb.RemoteRepo
|
||||||
|
|
||||||
srcRemoteRepo, err = context.CollectionFactory().RemoteRepoCollection().ByName(args[0])
|
srcRemoteRepo, err = context.CollectionFactory().RemoteRepoCollection().ByName(args[0])
|
||||||
@@ -115,18 +115,18 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toProcess, err := srcList.FilterWithProgress(queries, withDeps, dstList, context.DependencyOptions(), architecturesList, context.Progress())
|
toProcess, err := srcList.Filter(queries, withDeps, dstList, context.DependencyOptions(), architecturesList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to %s: %s", command, err)
|
return fmt.Errorf("unable to %s: %s", command, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var verb string
|
var verb string
|
||||||
|
|
||||||
if command == "move" { // nolint: goconst
|
if command == "move" {
|
||||||
verb = "moved"
|
verb = "moved"
|
||||||
} else if command == "copy" { // nolint: goconst
|
} else if command == "copy" {
|
||||||
verb = "copied"
|
verb = "copied"
|
||||||
} else if command == "import" { // nolint: goconst
|
} else if command == "import" {
|
||||||
verb = "imported"
|
verb = "imported"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if command == "move" { // nolint: goconst
|
if command == "move" {
|
||||||
srcList.Remove(p)
|
srcList.Remove(p)
|
||||||
}
|
}
|
||||||
context.Progress().ColoredPrintf("@g[o]@| %s %s", p, verb)
|
context.Progress().ColoredPrintf("@g[o]@| %s %s", p, verb)
|
||||||
@@ -156,7 +156,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to save: %s", err)
|
return fmt.Errorf("unable to save: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if command == "move" { // nolint: goconst
|
if command == "move" {
|
||||||
srcRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(srcList))
|
srcRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(srcList))
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Update(srcRepo)
|
err = context.CollectionFactory().LocalRepoCollection().Update(srcRepo)
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
ctx "github.com/aptly-dev/aptly/context"
|
ctx "github.com/smira/aptly/context"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -8,9 +8,9 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -60,9 +60,9 @@ func aptlyServe(cmd *commander.Command, args []string) error {
|
|||||||
published := make(map[string]*deb.PublishedRepo, context.CollectionFactory().PublishedRepoCollection().Len())
|
published := make(map[string]*deb.PublishedRepo, context.CollectionFactory().PublishedRepoCollection().Len())
|
||||||
|
|
||||||
err = context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
err = context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
||||||
e := context.CollectionFactory().PublishedRepoCollection().LoadComplete(repo, context.CollectionFactory())
|
err := context.CollectionFactory().PublishedRepoCollection().LoadComplete(repo, context.CollectionFactory())
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sources = append(sources, repo.String())
|
sources = append(sources, repo.String())
|
||||||
@@ -90,13 +90,13 @@ func aptlyServe(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("# %s\ndeb http://%s:%s/%s %s %s\n",
|
fmt.Printf("# %s\ndeb http://%s:%s/%s %s %s\n",
|
||||||
repo, listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " "))
|
repo, listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " "))
|
||||||
|
|
||||||
if utils.StrSliceHasItem(repo.Architectures, deb.ArchitectureSource) {
|
if utils.StrSliceHasItem(repo.Architectures, "source") {
|
||||||
fmt.Printf("deb-src http://%s:%s/%s %s %s\n",
|
fmt.Printf("deb-src http://%s:%s/%s %s %s\n",
|
||||||
listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " "))
|
listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publicPath := context.GetPublishedStorage("").(aptly.FileSystemPublishedStorage).PublicPath()
|
publicPath := context.GetPublishedStorage("").(aptly.LocalPublishedStorage).PublicPath()
|
||||||
ShutdownContext()
|
ShutdownContext()
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
|
|||||||
snapshot *deb.Snapshot
|
snapshot *deb.Snapshot
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(args) == 4 && args[1] == "from" && args[2] == "mirror" { // nolint: goconst
|
if len(args) == 4 && args[1] == "from" && args[2] == "mirror" {
|
||||||
// aptly snapshot create snap from mirror mirror
|
// aptly snapshot create snap from mirror mirror
|
||||||
var repo *deb.RemoteRepo
|
var repo *deb.RemoteRepo
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create snapshot: %s", err)
|
return fmt.Errorf("unable to create snapshot: %s", err)
|
||||||
}
|
}
|
||||||
} else if len(args) == 4 && args[1] == "from" && args[2] == "repo" { // nolint: goconst
|
} else if len(args) == 4 && args[1] == "from" && args[2] == "repo" {
|
||||||
// aptly snapshot create snap from repo repo
|
// aptly snapshot create snap from repo repo
|
||||||
var repo *deb.LocalRepo
|
var repo *deb.LocalRepo
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -66,7 +66,7 @@ func aptlySnapshotFilter(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter with dependencies as requested
|
// Filter with dependencies as requested
|
||||||
result, err := packageList.FilterWithProgress(queries, withDeps, nil, context.DependencyOptions(), architecturesList, context.Progress())
|
result, err := packageList.Filter(queries, withDeps, nil, context.DependencyOptions(), architecturesList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to filter: %s", err)
|
return fmt.Errorf("unable to filter: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -96,7 +96,7 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter with dependencies as requested
|
// Filter with dependencies as requested
|
||||||
result, err := sourcePackageList.FilterWithProgress(queries, !noDeps, packageList, context.DependencyOptions(), architecturesList, context.Progress())
|
result, err := sourcePackageList.Filter(queries, !noDeps, packageList, context.DependencyOptions(), architecturesList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to pull: %s", err)
|
return fmt.Errorf("unable to pull: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+10
-13
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/query"
|
"github.com/smira/aptly/query"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -26,9 +26,8 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
|
|
||||||
var reflist *deb.PackageRefList
|
var reflist *deb.PackageRefList
|
||||||
|
|
||||||
if command == "snapshot" { // nolint: goconst
|
if command == "snapshot" {
|
||||||
var snapshot *deb.Snapshot
|
snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(name)
|
||||||
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to search: %s", err)
|
return fmt.Errorf("unable to search: %s", err)
|
||||||
}
|
}
|
||||||
@@ -40,8 +39,7 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
|
|
||||||
reflist = snapshot.RefList()
|
reflist = snapshot.RefList()
|
||||||
} else if command == "mirror" {
|
} else if command == "mirror" {
|
||||||
var repo *deb.RemoteRepo
|
repo, err := context.CollectionFactory().RemoteRepoCollection().ByName(name)
|
||||||
repo, err = context.CollectionFactory().RemoteRepoCollection().ByName(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to search: %s", err)
|
return fmt.Errorf("unable to search: %s", err)
|
||||||
}
|
}
|
||||||
@@ -52,9 +50,8 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
reflist = repo.RefList()
|
reflist = repo.RefList()
|
||||||
} else if command == "repo" { // nolint: goconst
|
} else if command == "repo" {
|
||||||
var repo *deb.LocalRepo
|
repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
|
||||||
repo, err = context.CollectionFactory().LocalRepoCollection().ByName(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to search: %s", err)
|
return fmt.Errorf("unable to search: %s", err)
|
||||||
}
|
}
|
||||||
@@ -102,8 +99,8 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := list.FilterWithProgress([]deb.PackageQuery{q}, withDeps,
|
result, err := list.Filter([]deb.PackageQuery{q}, withDeps,
|
||||||
nil, context.DependencyOptions(), architecturesList, context.Progress())
|
nil, context.DependencyOptions(), architecturesList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to search: %s", err)
|
return fmt.Errorf("unable to search: %s", err)
|
||||||
}
|
}
|
||||||
@@ -113,7 +110,7 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
format := context.Flags().Lookup("format").Value.String()
|
format := context.Flags().Lookup("format").Value.String()
|
||||||
PrintPackageList(result, format, "")
|
PrintPackageList(result, format)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -35,23 +34,20 @@ func aptlySnapshotShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("Sources:\n")
|
fmt.Printf("Sources:\n")
|
||||||
for _, sourceID := range snapshot.SourceIDs {
|
for _, sourceID := range snapshot.SourceIDs {
|
||||||
var name string
|
var name string
|
||||||
if snapshot.SourceKind == deb.SourceSnapshot {
|
if snapshot.SourceKind == "snapshot" {
|
||||||
var source *deb.Snapshot
|
source, err := context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
|
||||||
source, err = context.CollectionFactory().SnapshotCollection().ByUUID(sourceID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name = source.Name
|
name = source.Name
|
||||||
} else if snapshot.SourceKind == deb.SourceLocalRepo {
|
} else if snapshot.SourceKind == "local" {
|
||||||
var source *deb.LocalRepo
|
source, err := context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
|
||||||
source, err = context.CollectionFactory().LocalRepoCollection().ByUUID(sourceID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name = source.Name
|
name = source.Name
|
||||||
} else if snapshot.SourceKind == deb.SourceRemoteRepo {
|
} else if snapshot.SourceKind == "repo" {
|
||||||
var source *deb.RemoteRepo
|
source, err := context.CollectionFactory().RemoteRepoCollection().ByUUID(sourceID)
|
||||||
source, err = context.CollectionFactory().RemoteRepoCollection().ByUUID(sourceID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -82,7 +82,7 @@ func aptlyTaskRun(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
for i, command := range cmdList {
|
for i, command := range cmdList {
|
||||||
if !commandErrored {
|
if !commandErrored {
|
||||||
err = context.ReOpenDatabase()
|
err := context.ReOpenDatabase()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to reopen DB: %s", err)
|
return fmt.Errorf("failed to reopen DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# aptly-zsh
|
|
||||||
zsh completion for aptly
|
|
||||||
|
|
||||||
The zsh completion function and this README were imported from
|
|
||||||
[steinymity's repository](https://github.com/steinymity/aptly-zsh).
|
|
||||||
|
|
||||||
[Aptly](https://www.aptly.info/) is a great tool to setup Debian APT repositories
|
|
||||||
and mirrors. However, it's sometimes hard to remember all the command line
|
|
||||||
syntax and names of all options. Therefore I wrote this zsh completion modules
|
|
||||||
for aptly.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the terms of the MIT license. See file `LICENSE`
|
|
||||||
for details.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Clone/copy the file `_aptly` to a place in your `$fpath` (show with
|
|
||||||
`echo $fpath`), or create a new directory and extend the fpath:
|
|
||||||
|
|
||||||
mkdir -p ~/.zsh/functions
|
|
||||||
fpath=(~/.zsh/functions $fpath)
|
|
||||||
editor ~/.zsh/functions/_aptly
|
|
||||||
|
|
||||||
To profit most from the provided help messages and completions, make sure that
|
|
||||||
your zsh is setup properly. I have tested with the grml-zsh configuration that
|
|
||||||
is [available on Github](https://github.com/grml/grml-etc-core/) and on the
|
|
||||||
[grml homepage](http://grml.org/zsh/).
|
|
||||||
|
|
||||||
## Compatibility
|
|
||||||
|
|
||||||
The command line completion was developed based on the manpage of aptly 1.2.0
|
|
||||||
(currently in Debian Testing). However, most completions will work on older
|
|
||||||
versions (e.g., 0.9.7 in Debian Stable), too.
|
|
||||||
|
|
||||||
The completion function completes most arguments and options that can be passed
|
|
||||||
to aptly, including mirror/repository/snapshot/publish names. However, not all
|
|
||||||
arguments are handled yet. See the next section for known limitations.
|
|
||||||
|
|
||||||
## Known Bugs and Limitation
|
|
||||||
|
|
||||||
* Boolean options are always completed with an explicit value `true` or
|
|
||||||
`false`, although omitting the value is implicitly interpreted as `true`.
|
|
||||||
* The source and destination names of copy and move operations must not be the
|
|
||||||
same. This is currently not enforced.
|
|
||||||
* The package query and display format strings are currently not completed.
|
|
||||||
* Endpoints are not completed.
|
|
||||||
* In `publish snapshot` there is no connection between the number of
|
|
||||||
components passed to `-component` and the number of given snapshots to
|
|
||||||
publish. Furthermore, the help text for `endpoint:prefix` disappears
|
|
||||||
after its first possible location.
|
|
||||||
* In `publish switch` the distribution can be set independently of the
|
|
||||||
`endpoint:prefix` (i.e., all published distributions can be combined with
|
|
||||||
all published `endpoint:prefix`).
|
|
||||||
* Neither `publish switch` nor `publish update` check if publish was created
|
|
||||||
from a snapshot or directly from a local repo.
|
|
||||||
* Task commands are not completed. There are no commas added.
|
|
||||||
* `help` won't complete after a sub command (i.e., `aptly mirror list help`).
|
|
||||||
* Probably more, feel free to open issues, and submit patches/merge requests.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Maximilian Stein <m@steiny.biz>
|
|
||||||
2018-02-03
|
|
||||||
@@ -1,617 +0,0 @@
|
|||||||
#compdef aptly
|
|
||||||
################################################################################
|
|
||||||
# Copyright (C) 2018 Maximilian Stein <m@steiny.biz>
|
|
||||||
# Acknowledgement: Many texts where copied from aptly(1)
|
|
||||||
#
|
|
||||||
# This project is licensed under the terms of the MIT license.
|
|
||||||
# See file LICENSE for details.
|
|
||||||
################################################################################
|
|
||||||
# zsh completion script for Aptly (http://aptly.info/)
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
# see https://man.cx/aptly
|
|
||||||
|
|
||||||
local curcontext="$curcontext" state line cmd subcmd ret=1
|
|
||||||
|
|
||||||
local arch_list=(amd64 arm64 armel armhf i386 mips mipsel mips64el ppc64el s390x)
|
|
||||||
local bool="bool:{_wanted -V values expl 'bool' compadd true false}"
|
|
||||||
local dists=({wheezy,jessie,stretch}{,-updates,-backports,-backports-sloopy} buster sid experimental)
|
|
||||||
local components=(main contrib non-free)
|
|
||||||
local aptly_query="aptly package query: "
|
|
||||||
local aptly_format="aptly package display format: "
|
|
||||||
local aptly_uploaders="-uploaders-file=[uploaders.json to be used when including .changes into this repository]:uploaders file:_files -g '*.json'"
|
|
||||||
local keyring="*-keyring=[gpg keyring to use when verifying Release file (could be specified multiple times)]:keyring file:_files -g '*.gpg'"
|
|
||||||
|
|
||||||
# complete command
|
|
||||||
(( $+functions[_aptly-cmd] )) ||
|
|
||||||
_aptly-cmd() {
|
|
||||||
_values "aptly command category" \
|
|
||||||
"mirror[manage, update mirrors of remote repositories]" \
|
|
||||||
"repo[manage local package repositories, add, remove, move, copy packages]" \
|
|
||||||
"snapshot[create, merge, manage snapshots]" \
|
|
||||||
"package[perform operation on the whole collection of packages]" \
|
|
||||||
"publish[publish snapshot or local repository]" \
|
|
||||||
"db[cleanup database and package pool, recover database after failure]" \
|
|
||||||
"task[multi-command tasks]" \
|
|
||||||
"serve[quickly serve published repositories via HTTP]" \
|
|
||||||
"config[configuration management]" \
|
|
||||||
"graph[generate dependency graph]" \
|
|
||||||
"api[REST API service]"
|
|
||||||
ret=0
|
|
||||||
}
|
|
||||||
|
|
||||||
# complete subcommand
|
|
||||||
(( $+functions[_aptly-subcmd] )) ||
|
|
||||||
_aptly-subcmd() {
|
|
||||||
local cmd=$1
|
|
||||||
case $cmd in
|
|
||||||
mirror)
|
|
||||||
_values "mirror commands" \
|
|
||||||
"create[create new mirror of remote repository]" \
|
|
||||||
"list[show full list of mirrors]" \
|
|
||||||
"show[show details about a mirror]" \
|
|
||||||
"drop[delete a mirror]" \
|
|
||||||
"update[update a mirror]" \
|
|
||||||
"rename[change name of a mirror]" \
|
|
||||||
"edit[change settings of a mirror]" \
|
|
||||||
"search[search mirror for packages matching query]"
|
|
||||||
ret=0 ;;
|
|
||||||
repo)
|
|
||||||
_values "repo commands" \
|
|
||||||
"add[add packages to local repository]" \
|
|
||||||
"copy[copy packages between local repositories]" \
|
|
||||||
"create[create local repository]" \
|
|
||||||
"drop[delete local repository]" \
|
|
||||||
"edit[edit properties of local repository]" \
|
|
||||||
"import[import packages from mirror to local repository]" \
|
|
||||||
"list[list local repositories]" \
|
|
||||||
"move[move packages between local repositories]" \
|
|
||||||
"remove[remove packages from local repository]" \
|
|
||||||
"show[show details about local repository]" \
|
|
||||||
"rename[renames local repository]" \
|
|
||||||
"search[search repo for packages matching query]" \
|
|
||||||
"include[add packages to local repositories based on .changes files]"
|
|
||||||
ret=0 ;;
|
|
||||||
snapshot)
|
|
||||||
_values "snapshot commands" \
|
|
||||||
"create[create snapshot of mirror or local repository]" \
|
|
||||||
"list[list snapshots]" \
|
|
||||||
"show[show details about snapshot]" \
|
|
||||||
"verify[verify dependencies in snapshot]" \
|
|
||||||
"pull[pull packages from another snapshot]" \
|
|
||||||
"diff[show difference between two snapshots]" \
|
|
||||||
"merge[merge snapshots]" \
|
|
||||||
"drop[delete snapshot]" \
|
|
||||||
"rename[rename snapshot]" \
|
|
||||||
"search[search snapshot for packages matching query]" \
|
|
||||||
"filter[filter packages in snapshot producing another snapshot]"
|
|
||||||
ret=0 ;;
|
|
||||||
publish)
|
|
||||||
_values "publish commands" \
|
|
||||||
"drop[remove published repository]" \
|
|
||||||
"list[list published repositories]" \
|
|
||||||
"repo[publish local repository]" \
|
|
||||||
"snapshot[publish snapshot]" \
|
|
||||||
"switch[update published repository by switching to new snapshot]" \
|
|
||||||
"update[update published local repository]" \
|
|
||||||
"show[shows details of published repository]"
|
|
||||||
ret=0 ;;
|
|
||||||
package)
|
|
||||||
_values "package commands" \
|
|
||||||
"search[search for packages matching query]" \
|
|
||||||
"show[show details about packages matching query]"
|
|
||||||
ret=0 ;;
|
|
||||||
db)
|
|
||||||
_values "db commands" \
|
|
||||||
"cleanup[cleanup db and package pool]" \
|
|
||||||
"recover[recover db after crash]"
|
|
||||||
ret=0 ;;
|
|
||||||
serve)
|
|
||||||
# no subcommand here
|
|
||||||
_arguments '1:: :' \
|
|
||||||
'-listen=[host:port for HTTP listening]:host\:port: '
|
|
||||||
ret=0 ;;
|
|
||||||
api)
|
|
||||||
_values "api commands" \
|
|
||||||
"serve[start api http service]"
|
|
||||||
ret=0 ;;
|
|
||||||
graph)
|
|
||||||
# no subcommand here
|
|
||||||
_arguments '*:' \
|
|
||||||
'-format=[render graph to specified format]:image format:(png svg pdf)' \
|
|
||||||
'-layout=[create a more vertical or more horizontal graph layout]:layout:(horizontal vertical)' \
|
|
||||||
'-output=[specify output filename, default is to open result in viewer]:output file:_files'
|
|
||||||
ret=0 ;;
|
|
||||||
config)
|
|
||||||
_values "config commands" \
|
|
||||||
"show[show current aptly config]"
|
|
||||||
ret=0 ;;
|
|
||||||
task)
|
|
||||||
_values "task commands" \
|
|
||||||
"run[run aptly tasks]"
|
|
||||||
ret=0 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# complete parameters
|
|
||||||
(( $+functions[_aptly-param] )) ||
|
|
||||||
_aptly-param() {
|
|
||||||
local cmd=$1 subcmd=$2
|
|
||||||
|
|
||||||
local config=$opt_args[-config]
|
|
||||||
[[ -n $config ]] && config="-config=$config"
|
|
||||||
|
|
||||||
# get list of mirrors, or ' ' if none
|
|
||||||
get_mirrors() {
|
|
||||||
# retrieve list of mirrors
|
|
||||||
local mirrors=($(aptly $config mirror list -raw=true 2>/dev/null))
|
|
||||||
# a single space causes just the help text to be shown
|
|
||||||
[[ -z $mirrors ]] && mirrors=" " || mirrors="($mirrors)"
|
|
||||||
echo $mirrors
|
|
||||||
}
|
|
||||||
# get lists of repos or ' ' if none
|
|
||||||
get_repos() {
|
|
||||||
# retrieve repo list
|
|
||||||
local repos=($(aptly $config repo list -raw=true 2>/dev/null))
|
|
||||||
[[ -z $repos ]] && repos=" " || repos="($repos)"
|
|
||||||
echo $repos
|
|
||||||
}
|
|
||||||
# get list of snapshots or ' ' if none
|
|
||||||
get_snapshots() {
|
|
||||||
local snapshots=($(aptly $config snapshot list -raw=true 2>/dev/null))
|
|
||||||
[[ -z $snapshots ]] && snapshots=" " || snapshots="($snapshots)"
|
|
||||||
echo $snapshots
|
|
||||||
}
|
|
||||||
# get list of gpg keys or ' ' if none
|
|
||||||
get_gpg_key_ids() {
|
|
||||||
local gpg_keys=($(gpg --quiet --batch --keyid-format long --list-secret-keys --with-colons 2>/dev/null | grep '^sec' | cut -d ':' -f 5))
|
|
||||||
[[ -z $gpg_keys ]] && gpg_keys=" " || gpg_keys="($gpg_keys)"
|
|
||||||
echo $gpg_keys
|
|
||||||
}
|
|
||||||
|
|
||||||
ret=0
|
|
||||||
case $cmd in
|
|
||||||
mirror)
|
|
||||||
local mirrors=$(get_mirrors)
|
|
||||||
|
|
||||||
case $subcmd in
|
|
||||||
create)
|
|
||||||
_arguments \
|
|
||||||
"-filter=[filter packages in mirror]:$aptly_query" \
|
|
||||||
"-filter-with-deps=[when filtering, include dependencies of matching packages as well]:$bool" \
|
|
||||||
"-force-architecture=[(only with architecture list) skip check that requested architectures are listed in Release file]:$bool" \
|
|
||||||
"-force-components=[(only with component list) skip check that requested components are listed in Release file]:$bool" \
|
|
||||||
"-ignore-signatures=[disable verification of Release file signatures]:$bool" \
|
|
||||||
$keyring \
|
|
||||||
"-with-sources=[download source packages in addition to binary packages]:$bool" \
|
|
||||||
"-with-udebs=[download .udeb packages (Debian installer support)]:$bool" \
|
|
||||||
"(-)2:new mirror name: " ":archive url:_urls" ":distribution:($dists)" "*:components:_values -s ' ' components $components"
|
|
||||||
;;
|
|
||||||
list)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-raw=[display list in machine-readable format]:$bool"
|
|
||||||
;;
|
|
||||||
show)
|
|
||||||
_arguments \
|
|
||||||
"-with-packages=[show detailed list of packages and versions stored in the mirror]:$bool" \
|
|
||||||
"(-)2:mirror name:$mirrors"
|
|
||||||
;;
|
|
||||||
drop)
|
|
||||||
_arguments \
|
|
||||||
"-force=[force mirror deletion even if used by snapshots]:$bool" \
|
|
||||||
"(-)2:mirror name:$mirrors"
|
|
||||||
;;
|
|
||||||
update)
|
|
||||||
_arguments \
|
|
||||||
"-download-limit=[limit download speed (kB/s)]:kB/s: " \
|
|
||||||
"-force=[force update mirror even if it is locked by another process]:$bool" \
|
|
||||||
"-ignore-checksums=[ignore checksum mismatches while downloading package files and metadata]:$bool" \
|
|
||||||
"-ignore-signatures=[disable verification of Release file signatures]:$bool" \
|
|
||||||
$keyring \
|
|
||||||
"-max-tries=[max download tries till process fails with download error]:number: " \
|
|
||||||
"-skip-existing-packages=[do not check file existence for packages listed in the internal database of the mirror]:$bool" \
|
|
||||||
"(-)2:mirror name:$mirrors"
|
|
||||||
;;
|
|
||||||
rename)
|
|
||||||
_arguments \
|
|
||||||
"2:old mirror name:$mirrors" ":new mirror name: "
|
|
||||||
;;
|
|
||||||
edit)
|
|
||||||
_arguments \
|
|
||||||
"-filter=[filter packages in mirror]:$aptly_query" \
|
|
||||||
"-filter-with-deps=[when filtering, include dependencies of matching packages as well]:$bool" \
|
|
||||||
"-with-sources=[download source packages in addition to binary packages]:$bool" \
|
|
||||||
"-with-udebs=[download .udeb packages (Debian installer support)]:$bool" \
|
|
||||||
"(-)2:mirror name:$mirrors"
|
|
||||||
;;
|
|
||||||
search)
|
|
||||||
_arguments \
|
|
||||||
"-format=[custom format for result printing]:$aptly_format" \
|
|
||||||
"-with-deps=[include dependencies into search results]:$bool" \
|
|
||||||
"(-)2:mirror name:$mirrors" ":$aptly_query"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
|
|
||||||
repo)
|
|
||||||
|
|
||||||
|
|
||||||
local repos=$(get_repos)
|
|
||||||
|
|
||||||
local create_edit=("-comment=[any text that would be used to described local repository]:comment: "
|
|
||||||
"-component=[default component when publishing]:component:($components)"
|
|
||||||
"-distribution=[default distribution when publishing]:distribution:($dists)"
|
|
||||||
$aptly_uploaders
|
|
||||||
)
|
|
||||||
|
|
||||||
case $subcmd in
|
|
||||||
add)
|
|
||||||
_arguments \
|
|
||||||
"-force-replace=[when adding package that conflicts with existing package, remove existing package]:$bool" \
|
|
||||||
"-remove-files=[remove files that have been imported successfully into repository]:$bool" \
|
|
||||||
"(-)2:repo name:$repos" "*:package files:_files -g '*.{udeb,deb,dsc}'"
|
|
||||||
;;
|
|
||||||
copy)
|
|
||||||
_arguments \
|
|
||||||
"-dry-run=[don’t copy, just show what would be copied]:$bool" \
|
|
||||||
"-with-deps=[follow dependencies when processing package−spec]:$$bool" \
|
|
||||||
"(-)2:src repo name:$repos" ":dest repo name:$repos" "*:$aptly_query"
|
|
||||||
;;
|
|
||||||
create)
|
|
||||||
local snapshots=$(get_snapshots)
|
|
||||||
|
|
||||||
_arguments \
|
|
||||||
${create_edit[@]} \
|
|
||||||
"(-)2:new repo name: " \
|
|
||||||
"3:::('from')" "4:::('snapshot')" "5::snapshot:$snapshots"
|
|
||||||
;;
|
|
||||||
drop)
|
|
||||||
_arguments \
|
|
||||||
"-force=[force local repo deletion even if used by snapshots]:$bool" \
|
|
||||||
"(-)2:repo name:$repos"
|
|
||||||
;;
|
|
||||||
edit)
|
|
||||||
_arguments \
|
|
||||||
${create_edit[@]} \
|
|
||||||
"(-)2:repo name:$repos"
|
|
||||||
;;
|
|
||||||
import)
|
|
||||||
local mirrors=$(get_mirrors)
|
|
||||||
|
|
||||||
_arguments \
|
|
||||||
"-dry-run=[don’t import, just show what would be imported]:$bool" \
|
|
||||||
"-with-deps=[follow dependencies when processing package−spec]:$bool" \
|
|
||||||
"(-)2:src mirror name:$mirrors" ":dest repo name:$repos" "*:$aptly_query"
|
|
||||||
;;
|
|
||||||
list)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-raw=[display list in machine−readable format]:$bool"
|
|
||||||
;;
|
|
||||||
move)
|
|
||||||
_arguments \
|
|
||||||
"-dry-run=[don’t move, just show what would be moved]:$bool" \
|
|
||||||
"-with-deps=[follow dependencies when processing package−spec]:$bool" \
|
|
||||||
"(-)2:srv repo name:$repos" ":dest repo name:$repos" "*:$aptly_query"
|
|
||||||
;;
|
|
||||||
remove)
|
|
||||||
_arguments \
|
|
||||||
"-dry-run=[don’t remove, just show what would be removed]:$bool" \
|
|
||||||
"(-)2:repo name:$repos" "*:$aptly_query"
|
|
||||||
;;
|
|
||||||
show)
|
|
||||||
_arguments \
|
|
||||||
"-with-packages=[show list of packages]:$bool" \
|
|
||||||
"(-)2:repo name:$repos"
|
|
||||||
;;
|
|
||||||
rename)
|
|
||||||
_arguments \
|
|
||||||
"2:old repo name:$repos" ":new repo name: "
|
|
||||||
;;
|
|
||||||
search)
|
|
||||||
_arguments \
|
|
||||||
"-format=[custom format for result printing]:$aptly_format" \
|
|
||||||
"-with-deps=[include dependencies into search results]:$bool" \
|
|
||||||
"(-)2:repo name:$repos" ":$aptly_query"
|
|
||||||
;;
|
|
||||||
include)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-accept-unsigned=[accept unsigned .changes files]:$bool" \
|
|
||||||
"-force-replace=[when adding package that conflicts with existing package, remove existing package]:$bool" \
|
|
||||||
"-ignore-signatures=[disable verification of .changes file signature]:$bool" \
|
|
||||||
$keyring \
|
|
||||||
"-no-remove-files=[don’t remove files that have been imported successfully into repository]:$bool" \
|
|
||||||
"-repo=[which repo should files go to, defaults to Distribution field of .changes file]:repo name:$repos" \
|
|
||||||
$aptly_uploaders \
|
|
||||||
"(-)*:changes files/directories:_files -g '*.changes'"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
snapshot)
|
|
||||||
local snapshots=$(get_snapshots)
|
|
||||||
|
|
||||||
case $subcmd in
|
|
||||||
create)
|
|
||||||
local mirrors=$(get_mirrors)
|
|
||||||
local repos=$(get_repos)
|
|
||||||
|
|
||||||
_arguments -C \
|
|
||||||
'(-)2:new snapshot name: ' \
|
|
||||||
'3: :->src1' \
|
|
||||||
'4:: :->src2' '5:: :->src3'
|
|
||||||
|
|
||||||
case $state in
|
|
||||||
src1)
|
|
||||||
_values 'snapshot src' 'from' 'empty' ;;
|
|
||||||
src2)
|
|
||||||
if [[ $line[3] == from ]]; then
|
|
||||||
_values 'snapshot src' 'mirror' 'repo'
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
src3)
|
|
||||||
if [[ $line[3] == from ]]; then
|
|
||||||
case $line[4] in
|
|
||||||
mirror)
|
|
||||||
_arguments "5:mirror name:$mirrors" ;;
|
|
||||||
repo)
|
|
||||||
_arguments "5:repo name:$repos" ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
list)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-raw=[display list in machine−readable format]:$bool" \
|
|
||||||
"-sort=[display list in ’name’ or creation ’time’ order]:sort order:((name\:'alphabetical order' time\:'chronological order'))"
|
|
||||||
;;
|
|
||||||
show)
|
|
||||||
_arguments \
|
|
||||||
"-with-packages=[show list of packages]:$bool" \
|
|
||||||
"(-)2:snapshot name:$snapshots"
|
|
||||||
;;
|
|
||||||
verify)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"(-)2:snapshot name:$snapshots" "*::more snapshots:$snapshots"
|
|
||||||
;;
|
|
||||||
pull)
|
|
||||||
_arguments \
|
|
||||||
"-all-matches=[pull all the packages that satisfy the dependency version requirements]:$bool" \
|
|
||||||
"-dry-run=[don’t create destination snapshot, just show what would be pulled]:$bool" \
|
|
||||||
"-no-deps=[don’t process dependencies, just pull listed packages]:$bool" \
|
|
||||||
"-no-remove=[don’t remove other package versions when pulling package]:$bool" \
|
|
||||||
"(-)2:to snapshot name:$snapshots" "3:src snapshot name:$snapshots" "4:new dest snapshot name: " \
|
|
||||||
"*:$aptly_query"
|
|
||||||
;;
|
|
||||||
diff)
|
|
||||||
_arguments \
|
|
||||||
"-only-matching=[display diff only for matching packages (don’t display missing packages)]:$bool" \
|
|
||||||
"(-)2:snapshot name a:$snapshots" "3:snapshot name b:$snapshots"
|
|
||||||
;;
|
|
||||||
merge)
|
|
||||||
_arguments \
|
|
||||||
"-latest=[use only the latest version of each package]:$bool" \
|
|
||||||
"-no-remove=[don’t remove duplicate arch/name packages]:$bool" \
|
|
||||||
"(-)2:new dest snapshot name: " "*:source snapshot name(s):$snapshots"
|
|
||||||
;;
|
|
||||||
drop)
|
|
||||||
_arguments \
|
|
||||||
"-force=[remove snapshot even if it was used as source for other snapshots]:$bool" \
|
|
||||||
"(-)2:snapshot name:$snapshots"
|
|
||||||
;;
|
|
||||||
rename)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"2:old snapshot name:$snapshots" "3:new snapshot name: "
|
|
||||||
;;
|
|
||||||
search)
|
|
||||||
_arguments \
|
|
||||||
"-format=[custom format for result printing]:$aptly_format" \
|
|
||||||
"-with-deps=[include dependencies into search results]:$bool" \
|
|
||||||
"(-)2:snapshot name:$snapshots" ":$aptly_query"
|
|
||||||
;;
|
|
||||||
filter)
|
|
||||||
_arguments \
|
|
||||||
"-with-deps=[include dependent packages as well]:$bool" \
|
|
||||||
"(-)2:src snapshot name:$snapshots" "3:new dest snapshot name: " "*:$aptly_query"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
publish)
|
|
||||||
# read lines of output into
|
|
||||||
# format of each item: <ep:prefix> <distribution>
|
|
||||||
local -a publish_prefixes
|
|
||||||
local -a publish_dists
|
|
||||||
for line in ${(@f)"$(aptly $config publish list -raw=true 2>/dev/null)"}
|
|
||||||
{
|
|
||||||
publish_prefixes+=($line[(ws: :)1])
|
|
||||||
publish_dists+=($line[(ws: :)2])
|
|
||||||
}
|
|
||||||
publish_prefixes_uniq=(${(@u)publish_prefixes})
|
|
||||||
publish_dists_uniq=(${(@u)publish_dists})
|
|
||||||
[[ -z $publish_prefixes_uniq ]] && publish_prefixes_uniq=" " || publish_prefixes_uniq="($publish_prefixes_uniq)"
|
|
||||||
[[ -z $publish_dists_uniq ]] && publish_dists_uniq=" " || publish_dists_uniq="($publish_dists_uniq)"
|
|
||||||
|
|
||||||
local gpg_keys=$(get_gpg_key_ids)
|
|
||||||
|
|
||||||
# common options for publishing
|
|
||||||
# TODO: is the keyring parameter correct?
|
|
||||||
local publish_update_options=(
|
|
||||||
"-batch=[run GPG with detached tty]:$bool"
|
|
||||||
"-force-overwrite=[overwrite files in package pool in case of mismatch]:$bool"
|
|
||||||
"-gpg-key=[GPG key ID to use when signing the release]:gpg key id:$gpg_keys"
|
|
||||||
"-keyring=[GPG keyring to use (instead of default)]:keyring file:_files -g '*.gpg'"
|
|
||||||
"-passphrase=[GPG passhprase for the key (warning: could be insecure)]:passphrase: "
|
|
||||||
"-passphrase-file=[GPG passhprase−file for the key (warning: could be insecure)]:passphrase file:_files"
|
|
||||||
"-secret-keyring=[GPG secret keyring to use (instead of default)]:secret-keyring:_files"
|
|
||||||
"-skip-contents=[don’t generate Contents indexes]:$bool"
|
|
||||||
"-skip-signing=[don’t sign Release files with GPG]:$bool"
|
|
||||||
)
|
|
||||||
local components_options=(
|
|
||||||
"-component=[component name to publish (for multi−component publishing, separate components with commas)]:components:_values -s , components $components"
|
|
||||||
)
|
|
||||||
local publish_options=(
|
|
||||||
"-butautomaticupgrades=[set value for ButAutomaticUpgrades field]:$bool"
|
|
||||||
"-distribution=[distribution name to publish]:distribution:($dists)"
|
|
||||||
"-label=[label to publish]:label: "
|
|
||||||
"-notautomatic=[set value for NotAutomatic field]:notautomatic: "
|
|
||||||
"-origin=[origin name to publish]:origin: "
|
|
||||||
${components_options[@]}
|
|
||||||
)
|
|
||||||
|
|
||||||
local endpoint_prefix="[endpoint\:]prefix"
|
|
||||||
|
|
||||||
case $subcmd in
|
|
||||||
repo)
|
|
||||||
local repos=$(get_repos)
|
|
||||||
_arguments \
|
|
||||||
${publish_options[@]} \
|
|
||||||
${publish_update_options[@]} \
|
|
||||||
"(-)2:repo name:$repos" "3::$endpoint_prefix: "
|
|
||||||
;;
|
|
||||||
snapshot)
|
|
||||||
local snapshots=$(get_snapshots)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
${publish_options[@]} \
|
|
||||||
${publish_update_options[@]} \
|
|
||||||
"(-)*:snapshot name:$snapshots" "3::$endpoint_prefix: "
|
|
||||||
;;
|
|
||||||
switch)
|
|
||||||
local snapshots=$(get_snapshots)
|
|
||||||
_arguments \
|
|
||||||
${publish_update_options[@]} \
|
|
||||||
${components_options[@]} \
|
|
||||||
"(-)2:distribution:$publish_dists_uniq" "3::$endpoint_prefix:$publish_prefixes_uniq" \
|
|
||||||
"*:new snapshot name:$snapshots"
|
|
||||||
;;
|
|
||||||
update)
|
|
||||||
_arguments \
|
|
||||||
${publish_update_options[@]} \
|
|
||||||
"(-)2:distribution:$publish_dists_uniq" "3::$endpoint_prefix:$publish_prefixes_uniq"
|
|
||||||
;;
|
|
||||||
show)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"(-)2:distribution:$publish_dists_uniq" "3::$endpoint_prefix:$publish_prefixes_uniq"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
package)
|
|
||||||
case $subcmd in
|
|
||||||
search)
|
|
||||||
_arguments \
|
|
||||||
"-format=[custom format for result printing]:$aptly_format" \
|
|
||||||
"(-)2:$aptly_query"
|
|
||||||
;;
|
|
||||||
show)
|
|
||||||
_arguments \
|
|
||||||
"-with-files=[display information about files from package pool]:$bool" \
|
|
||||||
"-with-references=[display information about mirrors, snapshots and local repos referencing this package]:$bool" \
|
|
||||||
"(-)2:$aptly_query"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
db)
|
|
||||||
case $subcmd in
|
|
||||||
cleanup)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-dry-run=[don’t delete anything]:$bool" \
|
|
||||||
"-verbose=[be verbose when loading objects/removing them]:$bool"
|
|
||||||
;;
|
|
||||||
recover)
|
|
||||||
# nothing to complete...
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
serve)
|
|
||||||
# completed in _aptly-subcmd
|
|
||||||
;;
|
|
||||||
api)
|
|
||||||
case $subcmd in
|
|
||||||
serve)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"-listen=[host:port for HTTP listening or unix://path to listen on a Unix domain socket]:host\:port or unix\://path: " \
|
|
||||||
"-no-lock=[don’t lock the database]:$bool"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
graph)
|
|
||||||
# completed in _aptly-subcmd
|
|
||||||
;;
|
|
||||||
config)
|
|
||||||
case $subcmd in
|
|
||||||
show)
|
|
||||||
# nothing to do
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
task)
|
|
||||||
case $subcmd in
|
|
||||||
run)
|
|
||||||
_arguments '1:: :' \
|
|
||||||
"(2)-filename=[specifies the filename that contains the commands to run]:filename:_files" \
|
|
||||||
"(-filename)*::comma-separated command list: "
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# main completion
|
|
||||||
_arguments -C \
|
|
||||||
"-architectures=[list of architectures to consider (comma−separated), default to all available]:architectures:_values -s , architectures $arch_list" \
|
|
||||||
"-config=[location of configuration file]:file:_files -g '*.conf'" \
|
|
||||||
"-db-open-attempts=[number of attempts to open DB if it’s locked by other instance]:number:()" \
|
|
||||||
"-dep-follow-all-variants=[when processing dependencies, follow a & b if dependency is ’a|b’]:$bool" \
|
|
||||||
"-dep-follow-recommends=[when processing dependencies, follow Recommends]:$bool" \
|
|
||||||
"-dep-follow-source=[when processing dependencies, follow from binary to Source packages]:$bool" \
|
|
||||||
"-dep-follow-suggests=[when processing dependencies, follow Suggests]:$bool" \
|
|
||||||
"-dep-verbose-resolve=[when processing dependencies, print detailed logs]:$bool" \
|
|
||||||
"-gpg-provider=[PGP implementation]:gpg provider:((gpg\:'external gpg' internal\:'Go internal implementation'))" \
|
|
||||||
'(-)1: :->cmds' \
|
|
||||||
'2: :->subcmd' \
|
|
||||||
'*:: :->args' && ret=0
|
|
||||||
|
|
||||||
cmd=$line[1]
|
|
||||||
subcmd=$line[2]
|
|
||||||
|
|
||||||
case $state in
|
|
||||||
cmds)
|
|
||||||
_aptly-cmd
|
|
||||||
_arguments '(-)1:: :((help\:integrated\ command\ help))'
|
|
||||||
;;
|
|
||||||
subcmd)
|
|
||||||
case $cmd in
|
|
||||||
help)
|
|
||||||
_aptly-cmd
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
_aptly-subcmd $cmd
|
|
||||||
_arguments '(-)2:: :((help\:integrated\ command\ help))'
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
|
|
||||||
args)
|
|
||||||
# help anywhere in line?
|
|
||||||
if [[ ${line[(i)help]} -le ${#line} ]]; then
|
|
||||||
if [[ ${#line} -le 3 ]]; then
|
|
||||||
if [[ $line[1] == help ]]; then
|
|
||||||
_aptly-subcmd $subcmd
|
|
||||||
elif [[ $line[2] == help ]]; then
|
|
||||||
_aptly-subcmd $cmd
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
_aptly-param $cmd $subcmd
|
|
||||||
# this somehow destroys parameter completion, so disable it for now
|
|
||||||
#_arguments '(-)3:: :((help\:integrated\ command\ help))'
|
|
||||||
fi
|
|
||||||
ret=0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# mode: Shell-Script
|
|
||||||
# sh-indentation: 4
|
|
||||||
# indent-tabs-mode: nil
|
|
||||||
# sh-basic-offset: 4
|
|
||||||
# End:
|
|
||||||
# vim: ft=zsh sw=4 ts=4 et
|
|
||||||
@@ -1,633 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# (The MIT License)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Andrey Smirnov
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the 'Software'), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
|
|
||||||
__aptly_mirror_list()
|
|
||||||
{
|
|
||||||
aptly mirror list -raw
|
|
||||||
}
|
|
||||||
|
|
||||||
__aptly_repo_list()
|
|
||||||
{
|
|
||||||
aptly repo list -raw
|
|
||||||
}
|
|
||||||
|
|
||||||
__aptly_snapshot_list()
|
|
||||||
{
|
|
||||||
aptly snapshot list -raw
|
|
||||||
}
|
|
||||||
|
|
||||||
__aptly_published_distributions()
|
|
||||||
{
|
|
||||||
aptly publish list -raw | cut -d ' ' -f 2 | sort | uniq
|
|
||||||
}
|
|
||||||
|
|
||||||
__aptly_published_prefixes()
|
|
||||||
{
|
|
||||||
aptly publish list -raw | cut -d ' ' -f 1 | sort | uniq
|
|
||||||
}
|
|
||||||
|
|
||||||
__aptly_prefixes_for_distribution()
|
|
||||||
{
|
|
||||||
aptly publish list -raw | awk -v dist="$1" '{ if (dist == $2) print $1 }' | sort | uniq
|
|
||||||
}
|
|
||||||
|
|
||||||
_aptly()
|
|
||||||
{
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
|
|
||||||
commands="api config db graph mirror package publish repo serve snapshot task version"
|
|
||||||
options="-architectures= -config= -db-open-attempts= -dep-follow-all-variants -dep-follow-recommends -dep-follow-source -dep-follow-suggests -dep-verbose-resolve -gpg-provider="
|
|
||||||
db_subcommands="cleanup recover"
|
|
||||||
mirror_subcommands="create drop edit show list rename search update"
|
|
||||||
publish_subcommands="drop list repo snapshot switch update"
|
|
||||||
snapshot_subcommands="create diff drop filter list merge pull rename search show verify"
|
|
||||||
repo_subcommands="add copy create drop edit import include list move remove rename search show"
|
|
||||||
package_subcommands="search show"
|
|
||||||
task_subcommands="run"
|
|
||||||
config_subcommands="show"
|
|
||||||
api_subcommands="serve"
|
|
||||||
|
|
||||||
local cmd subcmd numargs numoptions i
|
|
||||||
|
|
||||||
numargs=0
|
|
||||||
numoptions=0
|
|
||||||
|
|
||||||
for (( i=1; i < $COMP_CWORD; i++ )); do
|
|
||||||
if [[ -n "$cmd" ]]; then
|
|
||||||
if [[ ! -n "$subcmd" ]]; then
|
|
||||||
subcmd=${COMP_WORDS[i]}
|
|
||||||
numargs=$(( COMP_CWORD - i - 1 ))
|
|
||||||
else
|
|
||||||
if [[ "${COMP_WORDS[i]}" == -* ]]; then
|
|
||||||
numoptions=$(( numoptions + 1 ))
|
|
||||||
numargs=$(( numargs - 1 ))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [[ ! "${COMP_WORDS[i]}" == -* ]]; then
|
|
||||||
cmd=${COMP_WORDS[i]}
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ! -n "$cmd" ]];
|
|
||||||
then
|
|
||||||
case "$cur" in
|
|
||||||
-*)
|
|
||||||
COMPREPLY=($(compgen -W "${options}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
COMPREPLY=($(compgen -W "${commands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -n "$subcmd" ]];
|
|
||||||
then
|
|
||||||
case "$prev" in
|
|
||||||
"db")
|
|
||||||
COMPREPLY=($(compgen -W "${db_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"mirror")
|
|
||||||
COMPREPLY=($(compgen -W "${mirror_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"repo")
|
|
||||||
COMPREPLY=($(compgen -W "${repo_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"snapshot")
|
|
||||||
COMPREPLY=($(compgen -W "${snapshot_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"publish")
|
|
||||||
COMPREPLY=($(compgen -W "${publish_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"package")
|
|
||||||
COMPREPLY=($(compgen -W "${package_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"task")
|
|
||||||
COMPREPLY=($(compgen -W "${task_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"config")
|
|
||||||
COMPREPLY=($(compgen -W "${config_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
"api")
|
|
||||||
COMPREPLY=($(compgen -W "${api_subcommands}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$cmd" in
|
|
||||||
"mirror")
|
|
||||||
case "$subcmd" in
|
|
||||||
"create")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-filter= -filter-with-deps -force-components -ignore-signatures -keyring= -with-sources -with-udebs" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"edit")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-archive-url= -filter= -filter-with-deps -ignore-signatures -keyring= -with-sources -with-udebs" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"show")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-packages" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"search")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-format= -with-deps" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"rename")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"drop")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"list")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-raw" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"update")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force -download-limit= -ignore-checksums -ignore-signatures -keyring= -skip-existing-packages" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"repo")
|
|
||||||
case "$subcmd" in
|
|
||||||
"add")
|
|
||||||
case $numargs in
|
|
||||||
0)
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force-replace -remove-files" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
1)
|
|
||||||
_filedir '@(deb|dsc|udeb)'
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"copy"|"move")
|
|
||||||
case $numargs in
|
|
||||||
0)
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-deps -dry-run" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
1)
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"create")
|
|
||||||
case $numargs in
|
|
||||||
0)
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-comment= -distribution= -component= -uploaders-file=" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
1)
|
|
||||||
COMPREPLY=($(compgen -W "from" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
COMPREPLY=($(compgen -W "snapshot" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"drop")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"edit")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-comment= -distribution= -component= -uploaders-file=" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"search")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-format= -with-deps" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"list")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-raw" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"include")
|
|
||||||
case $numargs in
|
|
||||||
0)
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-accept-unsigned -force-replace -ignore-signatures -keyring= -no-remove-files -repo= -uploaders-file=" -- ${cur}))
|
|
||||||
else
|
|
||||||
comptopt -o filenames 2>/dev/null
|
|
||||||
COMPREPLY=($(compgen -f -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"import")
|
|
||||||
case $numargs in
|
|
||||||
0)
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-deps -dry-run" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
1)
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"remove")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-dry-run" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"show")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-packages" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"rename")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"snapshot")
|
|
||||||
case "$subcmd" in
|
|
||||||
"create")
|
|
||||||
case $numargs in
|
|
||||||
1)
|
|
||||||
COMPREPLY=($(compgen -W "from empty" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
if [[ "$prev" == "from" ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "mirror repo" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
if [[ "$prev" == "mirror" ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
if [[ "$prev" == "repo" ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"diff")
|
|
||||||
if [[ $numargs -eq 0 ]] && [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-only-matching" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -lt 2 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"drop")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"list")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-raw -sort=" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"merge")
|
|
||||||
if [[ $numargs -gt 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-latest" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"pull")
|
|
||||||
if [[ $numargs -eq 0 ]] && [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-all-matches -dry-run -no-deps -no-remove" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -lt 2 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"filter")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-deps" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"show")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-packages" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"search")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-format= -with-deps" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"rename")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"verify")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"publish")
|
|
||||||
case "$subcmd" in
|
|
||||||
"snapshot"|"repo")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-acquire-by-hash -batch -butautomaticupgrades= -component= -distribution= -force-overwrite -gpg-key= -keyring= -label= -notautomatic= -origin= -passphrase= -passphrase-file= -secret-keyring= -skip-contents -skip-signing" -- ${cur}))
|
|
||||||
else
|
|
||||||
if [[ "$subcmd" == "snapshot" ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_repo_list)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -eq 1 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_published_prefixes)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"list")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-raw" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"update")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-batch -force-overwrite -gpg-key= -keyring= -passphrase= -passphrase-file= -secret-keyring= -skip-cleanup -skip-contents -skip-signing" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_published_distributions)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -eq 1 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_prefixes_for_distribution $prev)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"switch")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-batch -force-overwrite -component= -gpg-key= -keyring= -passphrase= -passphrase-file= -secret-keyring= -skip-cleanup -skip-contents -skip-signing" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_published_distributions)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -eq 1 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_prefixes_for_distribution $prev)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -ge 2 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_snapshot_list)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"drop")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-force-drop -skip-cleanup" -- ${cur}))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_published_distributions)" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $numargs -eq 1 ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$(__aptly_prefixes_for_distribution $prev)" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"package")
|
|
||||||
case "$subcmd" in
|
|
||||||
"search")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-format=" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"show")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-with-files -with-references" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"serve")
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-listen=" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"graph")
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-format= -output=" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"api")
|
|
||||||
case "$subcmd" in
|
|
||||||
"serve")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-listen=" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"db")
|
|
||||||
case "$subcmd" in
|
|
||||||
"cleanup")
|
|
||||||
if [[ $numargs -eq 0 ]]; then
|
|
||||||
if [[ "$cur" == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "-dry-run -verbose" -- ${cur}))
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
} && complete -F _aptly aptly
|
|
||||||
+2
-14
@@ -2,17 +2,15 @@ package console
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
|
||||||
"github.com/cheggaaa/pb"
|
"github.com/cheggaaa/pb"
|
||||||
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/wsxiaoys/terminal/color"
|
"github.com/wsxiaoys/terminal/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
codePrint = iota
|
codePrint = iota
|
||||||
codePrintStdErr
|
|
||||||
codeProgress
|
codeProgress
|
||||||
codeHideProgress
|
codeHideProgress
|
||||||
codeStop
|
codeStop
|
||||||
@@ -30,6 +28,7 @@ type printTask struct {
|
|||||||
// Progress is a progress displaying subroutine, it allows to show download and other operations progress
|
// Progress is a progress displaying subroutine, it allows to show download and other operations progress
|
||||||
// mixed with progress bar
|
// mixed with progress bar
|
||||||
type Progress struct {
|
type Progress struct {
|
||||||
|
stop chan bool
|
||||||
stopped chan bool
|
stopped chan bool
|
||||||
queue chan printTask
|
queue chan printTask
|
||||||
bar *pb.ProgressBar
|
bar *pb.ProgressBar
|
||||||
@@ -129,11 +128,6 @@ func (p *Progress) Printf(msg string, a ...interface{}) {
|
|||||||
p.queue <- printTask{code: codePrint, message: fmt.Sprintf(msg, a...)}
|
p.queue <- printTask{code: codePrint, message: fmt.Sprintf(msg, a...)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintfStdErr does printf but in safe manner to stderr
|
|
||||||
func (p *Progress) PrintfStdErr(msg string, a ...interface{}) {
|
|
||||||
p.queue <- printTask{code: codePrintStdErr, message: fmt.Sprintf(msg, a...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ColoredPrintf does printf in colored way + newline
|
// ColoredPrintf does printf in colored way + newline
|
||||||
func (p *Progress) ColoredPrintf(msg string, a ...interface{}) {
|
func (p *Progress) ColoredPrintf(msg string, a ...interface{}) {
|
||||||
if RunningOnTerminal() {
|
if RunningOnTerminal() {
|
||||||
@@ -189,12 +183,6 @@ func (p *Progress) worker() {
|
|||||||
p.barShown = false
|
p.barShown = false
|
||||||
}
|
}
|
||||||
fmt.Print(task.message)
|
fmt.Print(task.message)
|
||||||
case codePrintStdErr:
|
|
||||||
if p.barShown {
|
|
||||||
fmt.Print("\r\033[2K")
|
|
||||||
p.barShown = false
|
|
||||||
}
|
|
||||||
fmt.Fprint(os.Stderr, task.message)
|
|
||||||
case codeProgress:
|
case codeProgress:
|
||||||
if hasBar {
|
if hasBar {
|
||||||
fmt.Print("\r" + task.message)
|
fmt.Print("\r" + task.message)
|
||||||
|
|||||||
+36
-118
@@ -2,11 +2,8 @@
|
|||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gocontext "context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
@@ -14,16 +11,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/console"
|
"github.com/smira/aptly/console"
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/aptly-dev/aptly/deb"
|
"github.com/smira/aptly/deb"
|
||||||
"github.com/aptly-dev/aptly/files"
|
"github.com/smira/aptly/files"
|
||||||
"github.com/aptly-dev/aptly/http"
|
"github.com/smira/aptly/http"
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/s3"
|
||||||
"github.com/aptly-dev/aptly/s3"
|
"github.com/smira/aptly/swift"
|
||||||
"github.com/aptly-dev/aptly/swift"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
)
|
)
|
||||||
@@ -32,8 +28,6 @@ import (
|
|||||||
type AptlyContext struct {
|
type AptlyContext struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
gocontext.Context
|
|
||||||
|
|
||||||
flags, globalFlags *flag.FlagSet
|
flags, globalFlags *flag.FlagSet
|
||||||
configLoaded bool
|
configLoaded bool
|
||||||
|
|
||||||
@@ -107,9 +101,6 @@ func (context *AptlyContext) config() *utils.ConfigStructure {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Config file not found, creating default config at %s\n\n", configLocations[0])
|
fmt.Fprintf(os.Stderr, "Config file not found, creating default config at %s\n\n", configLocations[0])
|
||||||
|
|
||||||
// as this is fresh aptly installation, we don't need to support legacy pool locations
|
|
||||||
utils.Config.SkipLegacyPool = true
|
|
||||||
utils.SaveConfig(configLocations[0], &utils.Config)
|
utils.SaveConfig(configLocations[0], &utils.Config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,9 +149,6 @@ func (context *AptlyContext) DependencyOptions() int {
|
|||||||
if context.lookupOption(context.config().DepFollowSource, "dep-follow-source") {
|
if context.lookupOption(context.config().DepFollowSource, "dep-follow-source") {
|
||||||
context.dependencyOptions |= deb.DepFollowSource
|
context.dependencyOptions |= deb.DepFollowSource
|
||||||
}
|
}
|
||||||
if context.lookupOption(context.config().DepVerboseResolve, "dep-verbose-resolve") {
|
|
||||||
context.dependencyOptions |= deb.DepVerboseResolve
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.dependencyOptions
|
return context.dependencyOptions
|
||||||
@@ -213,7 +201,8 @@ func (context *AptlyContext) Downloader() aptly.Downloader {
|
|||||||
if downloadLimit == 0 {
|
if downloadLimit == 0 {
|
||||||
downloadLimit = context.config().DownloadLimit
|
downloadLimit = context.config().DownloadLimit
|
||||||
}
|
}
|
||||||
context.downloader = http.NewDownloader(downloadLimit*1024, context._progress())
|
context.downloader = http.NewDownloader(context.config().DownloadConcurrency,
|
||||||
|
downloadLimit*1024, context._progress())
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.downloader
|
return context.downloader
|
||||||
@@ -244,34 +233,13 @@ func (context *AptlyContext) _database() (database.Storage, error) {
|
|||||||
if context.database == nil {
|
if context.database == nil {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
context.database, err = database.NewDB(context.dbPath())
|
context.database, err = database.OpenDB(context.dbPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't instantiate database: %s", err)
|
return nil, fmt.Errorf("can't open database: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tries := context.flags.Lookup("db-open-attempts").Value.Get().(int)
|
return context.database, nil
|
||||||
const BaseDelay = 10 * time.Second
|
|
||||||
const Jitter = 1 * time.Second
|
|
||||||
|
|
||||||
for ; tries >= 0; tries-- {
|
|
||||||
err := context.database.Open()
|
|
||||||
if err == nil || !strings.Contains(err.Error(), "resource temporarily unavailable") {
|
|
||||||
return context.database, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tries > 0 {
|
|
||||||
delay := time.Duration(rand.NormFloat64()*float64(Jitter) + float64(BaseDelay))
|
|
||||||
if delay < 0 {
|
|
||||||
delay = time.Second
|
|
||||||
}
|
|
||||||
|
|
||||||
context._progress().PrintfStdErr("Unable to open database, sleeping %s, attempts left %d...\n", delay, tries)
|
|
||||||
time.Sleep(delay)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseDatabase closes the db temporarily
|
// CloseDatabase closes the db temporarily
|
||||||
@@ -288,9 +256,26 @@ func (context *AptlyContext) CloseDatabase() error {
|
|||||||
|
|
||||||
// ReOpenDatabase reopens the db after close
|
// ReOpenDatabase reopens the db after close
|
||||||
func (context *AptlyContext) ReOpenDatabase() error {
|
func (context *AptlyContext) ReOpenDatabase() error {
|
||||||
_, err := context.Database()
|
context.Lock()
|
||||||
|
defer context.Unlock()
|
||||||
|
|
||||||
|
if context.database == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const MaxTries = 10
|
||||||
|
const Delay = 10 * time.Second
|
||||||
|
|
||||||
|
for try := 0; try < MaxTries; try++ {
|
||||||
|
err := context.database.ReOpen()
|
||||||
|
if err == nil || strings.Index(err.Error(), "resource temporarily unavailable") == -1 {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
context._progress().Printf("Unable to reopen database, sleeping %s\n", Delay)
|
||||||
|
<-time.After(Delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollectionFactory builds factory producing all kinds of collections
|
// CollectionFactory builds factory producing all kinds of collections
|
||||||
@@ -315,7 +300,7 @@ func (context *AptlyContext) PackagePool() aptly.PackagePool {
|
|||||||
defer context.Unlock()
|
defer context.Unlock()
|
||||||
|
|
||||||
if context.packagePool == nil {
|
if context.packagePool == nil {
|
||||||
context.packagePool = files.NewPackagePool(context.config().RootDir, !context.config().SkipLegacyPool)
|
context.packagePool = files.NewPackagePool(context.config().RootDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.packagePool
|
return context.packagePool
|
||||||
@@ -329,14 +314,7 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto
|
|||||||
publishedStorage, ok := context.publishedStorages[name]
|
publishedStorage, ok := context.publishedStorages[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
publishedStorage = files.NewPublishedStorage(filepath.Join(context.config().RootDir, "public"), "hardlink", "")
|
publishedStorage = files.NewPublishedStorage(context.config().RootDir)
|
||||||
} else if strings.HasPrefix(name, "filesystem:") {
|
|
||||||
params, ok := context.config().FileSystemPublishRoots[name[11:]]
|
|
||||||
if !ok {
|
|
||||||
Fatal(fmt.Errorf("published local storage %v not configured", name[11:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
publishedStorage = files.NewPublishedStorage(params.RootDir, params.LinkMethod, params.VerifyMethod)
|
|
||||||
} else if strings.HasPrefix(name, "s3:") {
|
} else if strings.HasPrefix(name, "s3:") {
|
||||||
params, ok := context.config().S3PublishRoots[name[3:]]
|
params, ok := context.config().S3PublishRoots[name[3:]]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -378,46 +356,6 @@ func (context *AptlyContext) UploadPath() string {
|
|||||||
return filepath.Join(context.Config().RootDir, "upload")
|
return filepath.Join(context.Config().RootDir, "upload")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *AptlyContext) pgpProvider() string {
|
|
||||||
var provider string
|
|
||||||
|
|
||||||
if context.globalFlags.IsSet("gpg-provider") {
|
|
||||||
provider = context.globalFlags.Lookup("gpg-provider").Value.String()
|
|
||||||
} else {
|
|
||||||
provider = context.config().GpgProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(provider == "gpg" || provider == "internal") { // nolint: goconst
|
|
||||||
Fatal(fmt.Errorf("unknown gpg provider: %v", provider))
|
|
||||||
}
|
|
||||||
|
|
||||||
return provider
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSigner returns Signer with respect to provider
|
|
||||||
func (context *AptlyContext) GetSigner() pgp.Signer {
|
|
||||||
context.Lock()
|
|
||||||
defer context.Unlock()
|
|
||||||
|
|
||||||
if context.pgpProvider() == "gpg" { // nolint: goconst
|
|
||||||
return pgp.NewGpgSigner()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pgp.GoSigner{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVerifier returns Verifier with respect to provider
|
|
||||||
func (context *AptlyContext) GetVerifier() pgp.Verifier {
|
|
||||||
context.Lock()
|
|
||||||
defer context.Unlock()
|
|
||||||
|
|
||||||
if context.pgpProvider() == "gpg" { // nolint: goconst
|
|
||||||
return pgp.NewGpgVerifier()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pgp.GoVerifier{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateFlags sets internal copy of flags in the context
|
// UpdateFlags sets internal copy of flags in the context
|
||||||
func (context *AptlyContext) UpdateFlags(flags *flag.FlagSet) {
|
func (context *AptlyContext) UpdateFlags(flags *flag.FlagSet) {
|
||||||
context.Lock()
|
context.Lock()
|
||||||
@@ -442,27 +380,6 @@ func (context *AptlyContext) GlobalFlags() *flag.FlagSet {
|
|||||||
return context.globalFlags
|
return context.globalFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoContextHandleSignals upgrades context to handle ^C by aborting context
|
|
||||||
func (context *AptlyContext) GoContextHandleSignals() {
|
|
||||||
context.Lock()
|
|
||||||
defer context.Unlock()
|
|
||||||
|
|
||||||
// Catch ^C
|
|
||||||
sigch := make(chan os.Signal)
|
|
||||||
signal.Notify(sigch, os.Interrupt)
|
|
||||||
|
|
||||||
var cancel gocontext.CancelFunc
|
|
||||||
|
|
||||||
context.Context, cancel = gocontext.WithCancel(context.Context)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-sigch
|
|
||||||
signal.Stop(sigch)
|
|
||||||
context.Progress().PrintfStdErr("Aborting... press ^C once again to abort immediately\n")
|
|
||||||
cancel()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown shuts context down
|
// Shutdown shuts context down
|
||||||
func (context *AptlyContext) Shutdown() {
|
func (context *AptlyContext) Shutdown() {
|
||||||
context.Lock()
|
context.Lock()
|
||||||
@@ -489,6 +406,7 @@ func (context *AptlyContext) Shutdown() {
|
|||||||
context.database = nil
|
context.database = nil
|
||||||
}
|
}
|
||||||
if context.downloader != nil {
|
if context.downloader != nil {
|
||||||
|
context.downloader.Abort()
|
||||||
context.downloader = nil
|
context.downloader = nil
|
||||||
}
|
}
|
||||||
if context.progress != nil {
|
if context.progress != nil {
|
||||||
@@ -503,6 +421,7 @@ func (context *AptlyContext) Cleanup() {
|
|||||||
defer context.Unlock()
|
defer context.Unlock()
|
||||||
|
|
||||||
if context.downloader != nil {
|
if context.downloader != nil {
|
||||||
|
context.downloader.Shutdown()
|
||||||
context.downloader = nil
|
context.downloader = nil
|
||||||
}
|
}
|
||||||
if context.progress != nil {
|
if context.progress != nil {
|
||||||
@@ -519,7 +438,6 @@ func NewContext(flags *flag.FlagSet) (*AptlyContext, error) {
|
|||||||
flags: flags,
|
flags: flags,
|
||||||
globalFlags: flags,
|
globalFlags: flags,
|
||||||
dependencyOptions: -1,
|
dependencyOptions: -1,
|
||||||
Context: gocontext.TODO(),
|
|
||||||
publishedStorages: map[string]aptly.PublishedStorage{},
|
publishedStorages: map[string]aptly.PublishedStorage{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
package context
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/smira/flag"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
|
||||||
|
|
||||||
type fatalErrorPanicChecker struct {
|
|
||||||
*CheckerInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
var FatalErrorPanicMatches Checker = &fatalErrorPanicChecker{
|
|
||||||
&CheckerInfo{Name: "FatalErrorPanics", Params: []string{"function", "expected"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func (checker *fatalErrorPanicChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
|
|
||||||
f := reflect.ValueOf(params[0])
|
|
||||||
if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
|
|
||||||
return false, "Function must take zero arguments"
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if errmsg != "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
obtained := recover()
|
|
||||||
|
|
||||||
names[0] = "panic"
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
var e1 *FatalError
|
|
||||||
if e1, ok = obtained.(*FatalError); ok {
|
|
||||||
params[0] = e1
|
|
||||||
} else {
|
|
||||||
errmsg = "Panic value is not FatalError"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var e2 *FatalError
|
|
||||||
if e2, ok = params[1].(*FatalError); ok {
|
|
||||||
params[1] = e2
|
|
||||||
} else {
|
|
||||||
errmsg = "Expected value is not FatalError"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if *e1 == *e2 {
|
|
||||||
result = true
|
|
||||||
} else {
|
|
||||||
result = false
|
|
||||||
errmsg = "Not equal"
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
f.Call(nil)
|
|
||||||
return false, "Function has not panicked"
|
|
||||||
}
|
|
||||||
|
|
||||||
type AptlyContextSuite struct {
|
|
||||||
context *AptlyContext
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Suite(&AptlyContextSuite{})
|
|
||||||
|
|
||||||
func (s *AptlyContextSuite) SetUpTest(c *C) {
|
|
||||||
flags := flag.NewFlagSet("fakeFlags", flag.ContinueOnError)
|
|
||||||
flags.String("config", "", "")
|
|
||||||
context, err := NewContext(flags)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
s.context = context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AptlyContextSuite) TestGetPublishedStorageBadFS(c *C) {
|
|
||||||
// https://github.com/aptly-dev/aptly/issues/711
|
|
||||||
// This will fail on account of us not having a config, so the
|
|
||||||
// storage never exists.
|
|
||||||
c.Assert(func() { s.context.GetPublishedStorage("filesystem:fuji") },
|
|
||||||
FatalErrorPanicMatches,
|
|
||||||
&FatalError{ReturnCode: 1, Message: "published local storage fuji not configured"})
|
|
||||||
}
|
|
||||||
+7
-13
@@ -32,8 +32,8 @@ type Storage interface {
|
|||||||
ProcessByPrefix(prefix []byte, proc StorageProcessor) error
|
ProcessByPrefix(prefix []byte, proc StorageProcessor) error
|
||||||
KeysByPrefix(prefix []byte) [][]byte
|
KeysByPrefix(prefix []byte) [][]byte
|
||||||
FetchByPrefix(prefix []byte) [][]byte
|
FetchByPrefix(prefix []byte) [][]byte
|
||||||
Open() error
|
|
||||||
Close() error
|
Close() error
|
||||||
|
ReOpen() error
|
||||||
StartBatch()
|
StartBatch()
|
||||||
FinishBatch() error
|
FinishBatch() error
|
||||||
CompactDB() error
|
CompactDB() error
|
||||||
@@ -66,19 +66,13 @@ func internalOpen(path string, throttleCompaction bool) (*leveldb.DB, error) {
|
|||||||
return leveldb.OpenFile(path, o)
|
return leveldb.OpenFile(path, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDB creates new instance of DB, but doesn't open it (yet)
|
// OpenDB opens (creates) LevelDB database
|
||||||
func NewDB(path string) (Storage, error) {
|
func OpenDB(path string) (Storage, error) {
|
||||||
return &levelDB{path: path}, nil
|
db, err := internalOpen(path, false)
|
||||||
}
|
|
||||||
|
|
||||||
// NewOpenDB creates new instance of DB and opens it
|
|
||||||
func NewOpenDB(path string) (Storage, error) {
|
|
||||||
db, err := NewDB(path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &levelDB{db: db, path: path}, nil
|
||||||
return db, db.Open()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecoverDB recovers LevelDB database from corruption
|
// RecoverDB recovers LevelDB database from corruption
|
||||||
@@ -221,8 +215,8 @@ func (l *levelDB) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reopen tries to open (re-open) the database
|
// Reopen tries to re-open the database
|
||||||
func (l *levelDB) Open() error {
|
func (l *levelDB) ReOpen() error {
|
||||||
if l.db != nil {
|
if l.db != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func (s *LevelDBSuite) SetUpTest(c *C) {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
s.path = c.MkDir()
|
s.path = c.MkDir()
|
||||||
s.db, err = NewOpenDB(s.path)
|
s.db, err = OpenDB(s.path)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ func (s *LevelDBSuite) TestRecoverDB(c *C) {
|
|||||||
err = RecoverDB(s.path)
|
err = RecoverDB(s.path)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
s.db, err = NewOpenDB(s.path)
|
s.db, err = OpenDB(s.path)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
result, err := s.db.Get(key)
|
result, err := s.db.Get(key)
|
||||||
@@ -223,7 +223,7 @@ func (s *LevelDBSuite) TestReOpen(c *C) {
|
|||||||
err = s.db.Close()
|
err = s.db.Close()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.db.Open()
|
err = s.db.ReOpen()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
result, err := s.db.Get(key)
|
result, err := s.db.Get(key)
|
||||||
|
|||||||
+14
-12
@@ -2,16 +2,14 @@ package deb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Changes is a result of .changes file parsing
|
// Changes is a result of .changes file parsing
|
||||||
@@ -25,7 +23,7 @@ type Changes struct {
|
|||||||
Binary []string
|
Binary []string
|
||||||
Architectures []string
|
Architectures []string
|
||||||
Stanza Stanza
|
Stanza Stanza
|
||||||
SignatureKeys []pgp.Key
|
SignatureKeys []utils.GpgKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChanges moves .changes file into temporary directory and creates Changes structure
|
// NewChanges moves .changes file into temporary directory and creates Changes structure
|
||||||
@@ -52,7 +50,7 @@ func NewChanges(path string) (*Changes, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyAndParse does optional signature verification and parses changes files
|
// VerifyAndParse does optional signature verification and parses changes files
|
||||||
func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier pgp.Verifier) error {
|
func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier utils.Verifier) error {
|
||||||
input, err := os.Open(filepath.Join(c.TempDir, c.ChangesName))
|
input, err := os.Open(filepath.Join(c.TempDir, c.ChangesName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -71,8 +69,7 @@ func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isClearSigned && !ignoreSignature {
|
if isClearSigned && !ignoreSignature {
|
||||||
var keyInfo *pgp.KeyInfo
|
keyInfo, err := verifier.VerifyClearsigned(input, false)
|
||||||
keyInfo, err = verifier.VerifyClearsigned(input, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -81,7 +78,7 @@ func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier
|
|||||||
c.SignatureKeys = keyInfo.GoodKeys
|
c.SignatureKeys = keyInfo.GoodKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
var text io.ReadCloser
|
var text *os.File
|
||||||
|
|
||||||
if isClearSigned {
|
if isClearSigned {
|
||||||
text, err = verifier.ExtractClearsigned(input)
|
text, err = verifier.ExtractClearsigned(input)
|
||||||
@@ -106,7 +103,11 @@ func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier
|
|||||||
c.Architectures = strings.Fields(c.Stanza["Architecture"])
|
c.Architectures = strings.Fields(c.Stanza["Architecture"])
|
||||||
|
|
||||||
c.Files, err = c.Files.ParseSumFields(c.Stanza)
|
c.Files, err = c.Files.ParseSumFields(c.Stanza)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare creates temporary directory, copies file there and verifies checksums
|
// Prepare creates temporary directory, copies file there and verifies checksums
|
||||||
@@ -172,7 +173,7 @@ func (c *Changes) PackageQuery() (PackageQuery, error) {
|
|||||||
|
|
||||||
// if c.Source is empty, this would never match
|
// if c.Source is empty, this would never match
|
||||||
sourceQuery := &AndQuery{
|
sourceQuery := &AndQuery{
|
||||||
L: &FieldQuery{Field: "$PackageType", Relation: VersionEqual, Value: ArchitectureSource},
|
L: &FieldQuery{Field: "$PackageType", Relation: VersionEqual, Value: "source"},
|
||||||
R: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: c.Source},
|
R: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: c.Source},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +181,8 @@ func (c *Changes) PackageQuery() (PackageQuery, error) {
|
|||||||
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
|
// matching debug ddeb packages, they're not present in the Binary field
|
||||||
var ddebQuery PackageQuery = &FieldQuery{Field: "Name", Relation: VersionEqual, Value: fmt.Sprintf("%s-dbgsym", c.Binary[0])}
|
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{
|
||||||
@@ -204,7 +206,7 @@ func (c *Changes) PackageQuery() (PackageQuery, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binaryQuery = &AndQuery{
|
binaryQuery = &AndQuery{
|
||||||
L: &NotQuery{Q: &FieldQuery{Field: "$PackageType", Relation: VersionEqual, Value: ArchitectureSource}},
|
L: &NotQuery{Q: &FieldQuery{Field: "$PackageType", Relation: VersionEqual, Value: "source"}},
|
||||||
R: binaryQuery}
|
R: binaryQuery}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package deb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
"github.com/ugorji/go/codec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChecksumCollection does management of ChecksumInfo in DB
|
|
||||||
type ChecksumCollection struct {
|
|
||||||
db database.Storage
|
|
||||||
codecHandle *codec.MsgpackHandle
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewChecksumCollection creates new ChecksumCollection and binds it to database
|
|
||||||
func NewChecksumCollection(db database.Storage) *ChecksumCollection {
|
|
||||||
return &ChecksumCollection{
|
|
||||||
db: db,
|
|
||||||
codecHandle: &codec.MsgpackHandle{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (collection *ChecksumCollection) dbKey(path string) []byte {
|
|
||||||
return []byte("C" + path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get finds checksums in DB by path
|
|
||||||
func (collection *ChecksumCollection) Get(path string) (*utils.ChecksumInfo, error) {
|
|
||||||
encoded, err := collection.db.Get(collection.dbKey(path))
|
|
||||||
if err != nil {
|
|
||||||
if err == database.ErrNotFound {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &utils.ChecksumInfo{}
|
|
||||||
|
|
||||||
decoder := codec.NewDecoderBytes(encoded, collection.codecHandle)
|
|
||||||
err = decoder.Decode(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update adds or updates information about checksum in DB
|
|
||||||
func (collection *ChecksumCollection) Update(path string, c *utils.ChecksumInfo) error {
|
|
||||||
var encodeBuffer bytes.Buffer
|
|
||||||
|
|
||||||
encoder := codec.NewEncoder(&encodeBuffer, collection.codecHandle)
|
|
||||||
err := encoder.Encode(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return collection.db.Put(collection.dbKey(path), encodeBuffer.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check interface
|
|
||||||
var (
|
|
||||||
_ aptly.ChecksumStorage = &ChecksumCollection{}
|
|
||||||
)
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package deb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ChecksumCollectionSuite struct {
|
|
||||||
collection *ChecksumCollection
|
|
||||||
c utils.ChecksumInfo
|
|
||||||
db database.Storage
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Suite(&ChecksumCollectionSuite{})
|
|
||||||
|
|
||||||
func (s *ChecksumCollectionSuite) SetUpTest(c *C) {
|
|
||||||
s.c = utils.ChecksumInfo{
|
|
||||||
Size: 124,
|
|
||||||
MD5: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
||||||
SHA1: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
||||||
SHA256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
||||||
}
|
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
|
||||||
s.collection = NewChecksumCollection(s.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ChecksumCollectionSuite) TearDownTest(c *C) {
|
|
||||||
s.db.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ChecksumCollectionSuite) TestFlow(c *C) {
|
|
||||||
// checksum not stored
|
|
||||||
checksum, err := s.collection.Get("some/path")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Check(checksum, IsNil)
|
|
||||||
|
|
||||||
// store checksum
|
|
||||||
err = s.collection.Update("some/path", &s.c)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
// load it back
|
|
||||||
checksum, err = s.collection.Get("some/path")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Check(*checksum, DeepEquals, s.c)
|
|
||||||
}
|
|
||||||
+1
-15
@@ -3,7 +3,7 @@ package deb
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
"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
|
||||||
@@ -15,7 +15,6 @@ type CollectionFactory struct {
|
|||||||
snapshots *SnapshotCollection
|
snapshots *SnapshotCollection
|
||||||
localRepos *LocalRepoCollection
|
localRepos *LocalRepoCollection
|
||||||
publishedRepos *PublishedRepoCollection
|
publishedRepos *PublishedRepoCollection
|
||||||
checksums *ChecksumCollection
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCollectionFactory creates new factory
|
// NewCollectionFactory creates new factory
|
||||||
@@ -90,18 +89,6 @@ func (factory *CollectionFactory) PublishedRepoCollection() *PublishedRepoCollec
|
|||||||
return factory.publishedRepos
|
return factory.publishedRepos
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChecksumCollection returns (or creates) new ChecksumCollection
|
|
||||||
func (factory *CollectionFactory) ChecksumCollection() *ChecksumCollection {
|
|
||||||
factory.Lock()
|
|
||||||
defer factory.Unlock()
|
|
||||||
|
|
||||||
if factory.checksums == nil {
|
|
||||||
factory.checksums = NewChecksumCollection(factory.db)
|
|
||||||
}
|
|
||||||
|
|
||||||
return factory.checksums
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush removes all references to collections, so that memory could be reclaimed
|
// Flush removes all references to collections, so that memory could be reclaimed
|
||||||
func (factory *CollectionFactory) Flush() {
|
func (factory *CollectionFactory) Flush() {
|
||||||
factory.Lock()
|
factory.Lock()
|
||||||
@@ -112,5 +99,4 @@ func (factory *CollectionFactory) Flush() {
|
|||||||
factory.remoteRepos = nil
|
factory.remoteRepos = nil
|
||||||
factory.publishedRepos = nil
|
factory.publishedRepos = nil
|
||||||
factory.packages = nil
|
factory.packages = nil
|
||||||
factory.checksums = nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -6,7 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/aptly"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
"github.com/smira/go-uuid/uuid"
|
"github.com/smira/go-uuid/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +26,10 @@ func NewContentsIndex(db database.Storage) *ContentsIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(qualifiedName []byte, contents []string) error {
|
func (index *ContentsIndex) Push(p *Package, packagePool aptly.PackagePool) error {
|
||||||
|
contents := p.Contents(packagePool)
|
||||||
|
qualifiedName := []byte(p.QualifiedName())
|
||||||
|
|
||||||
for _, path := range contents {
|
for _, path := range contents {
|
||||||
// for performance reasons we only write to leveldb during push.
|
// for performance reasons we only write to leveldb during push.
|
||||||
// merging of qualified names per path will be done in WriteTo
|
// merging of qualified names per path will be done in WriteTo
|
||||||
|
|||||||
+22
-47
@@ -12,20 +12,12 @@ import (
|
|||||||
|
|
||||||
"github.com/h2non/filetype/matchers"
|
"github.com/h2non/filetype/matchers"
|
||||||
"github.com/mkrautz/goar"
|
"github.com/mkrautz/goar"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/smira/go-xz"
|
"github.com/smira/go-xz"
|
||||||
"github.com/smira/lzma"
|
"github.com/smira/lzma"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Source kinds
|
|
||||||
const (
|
|
||||||
SourceSnapshot = "snapshot"
|
|
||||||
SourceLocalRepo = "local"
|
|
||||||
SourceRemoteRepo = "repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetControlFileFromDeb reads control file from deb package
|
// GetControlFileFromDeb reads control file from deb package
|
||||||
func GetControlFileFromDeb(packageFile string) (Stanza, error) {
|
func GetControlFileFromDeb(packageFile string) (Stanza, error) {
|
||||||
file, err := os.Open(packageFile)
|
file, err := os.Open(packageFile)
|
||||||
@@ -37,46 +29,21 @@ func GetControlFileFromDeb(packageFile string) (Stanza, error) {
|
|||||||
library := ar.NewReader(file)
|
library := ar.NewReader(file)
|
||||||
for {
|
for {
|
||||||
header, err := library.Next()
|
header, err := library.Next()
|
||||||
|
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil, fmt.Errorf("unable to find control.tar.* part in package %s", packageFile)
|
return nil, fmt.Errorf("unable to find control.tar.gz part in package %s", packageFile)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read .deb archive %s: %s", packageFile, err)
|
return nil, fmt.Errorf("unable to read .deb archive %s: %s", packageFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// As per deb(5) version 1.19.0.4 the control file may be:
|
if header.Name == "control.tar.gz" {
|
||||||
// - control.tar (since 1.17.6)
|
ungzip, err := gzip.NewReader(library)
|
||||||
// - control.tar.gz
|
|
||||||
// - control.tar.xz (since 1.17.6)
|
|
||||||
// Look for all of the above and uncompress as necessary.
|
|
||||||
if strings.HasPrefix(header.Name, "control.tar") {
|
|
||||||
bufReader := bufio.NewReader(library)
|
|
||||||
|
|
||||||
var tarInput io.Reader
|
|
||||||
|
|
||||||
switch header.Name {
|
|
||||||
case "control.tar":
|
|
||||||
tarInput = bufReader
|
|
||||||
case "control.tar.gz":
|
|
||||||
ungzip, err := gzip.NewReader(bufReader)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to ungzip %s from %s", header.Name, packageFile)
|
return nil, fmt.Errorf("unable to ungzip control file from %s. Error: %s", packageFile, err)
|
||||||
}
|
}
|
||||||
defer ungzip.Close()
|
defer ungzip.Close()
|
||||||
tarInput = ungzip
|
|
||||||
case "control.tar.xz":
|
|
||||||
unxz, err := xz.NewReader(bufReader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "unable to unxz %s from %s", header.Name, packageFile)
|
|
||||||
}
|
|
||||||
defer unxz.Close()
|
|
||||||
tarInput = unxz
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported tar compression in %s: %s", packageFile, header.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
untar := tar.NewReader(tarInput)
|
untar := tar.NewReader(ungzip)
|
||||||
for {
|
for {
|
||||||
tarHeader, err := untar.Next()
|
tarHeader, err := untar.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -101,7 +68,7 @@ func GetControlFileFromDeb(packageFile string) (Stanza, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetControlFileFromDsc reads control file from dsc package
|
// GetControlFileFromDsc reads control file from dsc package
|
||||||
func GetControlFileFromDsc(dscFile string, verifier pgp.Verifier) (Stanza, error) {
|
func GetControlFileFromDsc(dscFile string, verifier utils.Verifier) (Stanza, error) {
|
||||||
file, err := os.Open(dscFile)
|
file, err := os.Open(dscFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -115,7 +82,7 @@ func GetControlFileFromDsc(dscFile string, verifier pgp.Verifier) (Stanza, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var text io.ReadCloser
|
var text *os.File
|
||||||
|
|
||||||
if isClearSigned {
|
if isClearSigned {
|
||||||
text, err = verifier.ExtractClearsigned(file)
|
text, err = verifier.ExtractClearsigned(file)
|
||||||
@@ -138,7 +105,13 @@ func GetControlFileFromDsc(dscFile string, verifier pgp.Verifier) (Stanza, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetContentsFromDeb returns list of files installed by .deb package
|
// GetContentsFromDeb returns list of files installed by .deb package
|
||||||
func GetContentsFromDeb(file io.Reader, packageFile string) ([]string, error) {
|
func GetContentsFromDeb(packageFile string) ([]string, error) {
|
||||||
|
file, err := os.Open(packageFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
library := ar.NewReader(file)
|
library := ar.NewReader(file)
|
||||||
for {
|
for {
|
||||||
header, err := library.Next()
|
header, err := library.Next()
|
||||||
@@ -146,7 +119,7 @@ func GetContentsFromDeb(file io.Reader, packageFile string) ([]string, error) {
|
|||||||
return nil, fmt.Errorf("unable to find data.tar.* part in %s", packageFile)
|
return nil, fmt.Errorf("unable to find data.tar.* part in %s", packageFile)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to read .deb archive from %s", packageFile)
|
return nil, fmt.Errorf("unable to read .deb archive from %s: %s", packageFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(header.Name, "data.tar") {
|
if strings.HasPrefix(header.Name, "data.tar") {
|
||||||
@@ -169,7 +142,7 @@ func GetContentsFromDeb(file io.Reader, packageFile string) ([]string, error) {
|
|||||||
} else {
|
} else {
|
||||||
ungzip, err := gzip.NewReader(bufReader)
|
ungzip, err := gzip.NewReader(bufReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to ungzip data.tar.gz from %s", packageFile)
|
return nil, fmt.Errorf("unable to ungzip data.tar.gz from %s: %s", packageFile, err)
|
||||||
}
|
}
|
||||||
defer ungzip.Close()
|
defer ungzip.Close()
|
||||||
tarInput = ungzip
|
tarInput = ungzip
|
||||||
@@ -179,7 +152,7 @@ func GetContentsFromDeb(file io.Reader, packageFile string) ([]string, error) {
|
|||||||
case "data.tar.xz":
|
case "data.tar.xz":
|
||||||
unxz, err := xz.NewReader(bufReader)
|
unxz, err := xz.NewReader(bufReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to unxz data.tar.xz from %s", packageFile)
|
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
|
||||||
@@ -199,14 +172,16 @@ func GetContentsFromDeb(file io.Reader, packageFile string) ([]string, error) {
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to read .tar archive from %s", packageFile)
|
return nil, fmt.Errorf("unable to read .tar archive from %s: %s", packageFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tarHeader.Typeflag == tar.TypeDir {
|
if tarHeader.Typeflag == tar.TypeDir {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tarHeader.Name = strings.TrimPrefix(tarHeader.Name[2:], "./")
|
if strings.HasPrefix(tarHeader.Name, "./") {
|
||||||
|
tarHeader.Name = tarHeader.Name[2:]
|
||||||
|
}
|
||||||
results = append(results, tarHeader.Name)
|
results = append(results, tarHeader.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-21
@@ -1,17 +1,16 @@
|
|||||||
package deb
|
package deb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebSuite struct {
|
type DebSuite struct {
|
||||||
debFile, debFile2, debFileWithXzControl, dscFile, dscFileNoSign string
|
debFile, debFile2, dscFile, dscFileNoSign string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&DebSuite{})
|
var _ = Suite(&DebSuite{})
|
||||||
@@ -20,7 +19,6 @@ func (s *DebSuite) SetUpSuite(c *C) {
|
|||||||
_, _File, _, _ := runtime.Caller(0)
|
_, _File, _, _ := runtime.Caller(0)
|
||||||
s.debFile = filepath.Join(filepath.Dir(_File), "../system/files/libboost-program-options-dev_1.49.0.1_i386.deb")
|
s.debFile = filepath.Join(filepath.Dir(_File), "../system/files/libboost-program-options-dev_1.49.0.1_i386.deb")
|
||||||
s.debFile2 = filepath.Join(filepath.Dir(_File), "../system/changes/hardlink_0.2.1_amd64.deb")
|
s.debFile2 = filepath.Join(filepath.Dir(_File), "../system/changes/hardlink_0.2.1_amd64.deb")
|
||||||
s.debFileWithXzControl = filepath.Join(filepath.Dir(_File), "../system/changes/libqt5concurrent5-dbgsym_5.9.1+dfsg-2+18.04+bionic+build4_amd64.ddeb")
|
|
||||||
s.dscFile = filepath.Join(filepath.Dir(_File), "../system/files/pyspi_0.6.1-1.3.dsc")
|
s.dscFile = filepath.Join(filepath.Dir(_File), "../system/files/pyspi_0.6.1-1.3.dsc")
|
||||||
s.dscFileNoSign = filepath.Join(filepath.Dir(_File), "../system/files/pyspi-0.6.1-1.3.stripped.dsc")
|
s.dscFileNoSign = filepath.Join(filepath.Dir(_File), "../system/files/pyspi-0.6.1-1.3.stripped.dsc")
|
||||||
}
|
}
|
||||||
@@ -39,16 +37,8 @@ func (s *DebSuite) TestGetControlFileFromDeb(c *C) {
|
|||||||
c.Check(st["Package"], Equals, "libboost-program-options-dev")
|
c.Check(st["Package"], Equals, "libboost-program-options-dev")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DebSuite) TestGetControlFileFromDebWithXzControl(c *C) {
|
|
||||||
// Has control.tar.xz archive inside.
|
|
||||||
st, err := GetControlFileFromDeb(s.debFileWithXzControl)
|
|
||||||
c.Check(err, IsNil)
|
|
||||||
c.Check(st["Version"], Equals, "5.9.1+dfsg-2+18.04+bionic+build4")
|
|
||||||
c.Check(st["Package"], Equals, "libqt5concurrent5-dbgsym")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DebSuite) TestGetControlFileFromDsc(c *C) {
|
func (s *DebSuite) TestGetControlFileFromDsc(c *C) {
|
||||||
verifier := &pgp.GoVerifier{}
|
verifier := &utils.GpgVerifier{}
|
||||||
|
|
||||||
_, err := GetControlFileFromDsc("/no/such/file", verifier)
|
_, err := GetControlFileFromDsc("/no/such/file", verifier)
|
||||||
c.Check(err, ErrorMatches, ".*no such file or directory")
|
c.Check(err, ErrorMatches, ".*no such file or directory")
|
||||||
@@ -69,19 +59,13 @@ func (s *DebSuite) TestGetControlFileFromDsc(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *DebSuite) TestGetContentsFromDeb(c *C) {
|
func (s *DebSuite) TestGetContentsFromDeb(c *C) {
|
||||||
f, err := os.Open(s.debFile)
|
contents, err := GetContentsFromDeb(s.debFile)
|
||||||
c.Assert(err, IsNil)
|
|
||||||
contents, err := GetContentsFromDeb(f, s.debFile)
|
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(contents, DeepEquals, []string{"usr/share/doc/libboost-program-options-dev/changelog.gz",
|
c.Check(contents, DeepEquals, []string{"usr/share/doc/libboost-program-options-dev/changelog.gz",
|
||||||
"usr/share/doc/libboost-program-options-dev/copyright"})
|
"usr/share/doc/libboost-program-options-dev/copyright"})
|
||||||
c.Assert(f.Close(), IsNil)
|
|
||||||
|
|
||||||
f, err = os.Open(s.debFile2)
|
contents, err = GetContentsFromDeb(s.debFile2)
|
||||||
c.Assert(err, IsNil)
|
|
||||||
contents, err = GetContentsFromDeb(f, s.debFile2)
|
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(contents, DeepEquals, []string{"usr/bin/hardlink", "usr/share/man/man1/hardlink.1.gz",
|
c.Check(contents, DeepEquals, []string{"usr/bin/hardlink", "usr/share/man/man1/hardlink.1.gz",
|
||||||
"usr/share/doc/hardlink/changelog.gz", "usr/share/doc/hardlink/copyright", "usr/share/doc/hardlink/NEWS.Debian.gz"})
|
"usr/share/doc/hardlink/changelog.gz", "usr/share/doc/hardlink/copyright", "usr/share/doc/hardlink/NEWS.Debian.gz"})
|
||||||
c.Assert(f.Close(), IsNil)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-9
@@ -11,9 +11,6 @@ import (
|
|||||||
// Stanza or paragraph of Debian control file
|
// Stanza or paragraph of Debian control file
|
||||||
type Stanza map[string]string
|
type Stanza map[string]string
|
||||||
|
|
||||||
// MaxFieldSize is maximum stanza field size in bytes
|
|
||||||
const MaxFieldSize = 2 * 1024 * 1024
|
|
||||||
|
|
||||||
// Canonical order of fields in stanza
|
// Canonical order of fields in stanza
|
||||||
// Taken from: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/vivid/apt/vivid/view/head:/apt-pkg/tagfile.cc#L504
|
// Taken from: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/vivid/apt/vivid/view/head:/apt-pkg/tagfile.cc#L504
|
||||||
var (
|
var (
|
||||||
@@ -25,8 +22,6 @@ var (
|
|||||||
"Version",
|
"Version",
|
||||||
"Codename",
|
"Codename",
|
||||||
"Date",
|
"Date",
|
||||||
"NotAutomatic",
|
|
||||||
"ButAutomaticUpgrades",
|
|
||||||
"Architectures",
|
"Architectures",
|
||||||
"Architecture",
|
"Architecture",
|
||||||
"Components",
|
"Components",
|
||||||
@@ -217,10 +212,7 @@ type ControlFileReader struct {
|
|||||||
|
|
||||||
// NewControlFileReader creates ControlFileReader, it wraps with buffering
|
// NewControlFileReader creates ControlFileReader, it wraps with buffering
|
||||||
func NewControlFileReader(r io.Reader) *ControlFileReader {
|
func NewControlFileReader(r io.Reader) *ControlFileReader {
|
||||||
scnr := bufio.NewScanner(bufio.NewReaderSize(r, 32768))
|
return &ControlFileReader{scanner: bufio.NewScanner(bufio.NewReaderSize(r, 32768))}
|
||||||
scnr.Buffer(nil, MaxFieldSize)
|
|
||||||
|
|
||||||
return &ControlFileReader{scanner: scnr}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadStanza reeads one stanza from control file
|
// ReadStanza reeads one stanza from control file
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package deb
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
@@ -136,17 +135,6 @@ func (s *ControlFileSuite) TestCanonicalCase(c *C) {
|
|||||||
c.Check(canonicalCase("packaGe-lIst"), Equals, "Package-List")
|
c.Check(canonicalCase("packaGe-lIst"), Equals, "Package-List")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ControlFileSuite) TestLongFields(c *C) {
|
|
||||||
f, err := os.Open("long.stanza")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
r := NewControlFileReader(f)
|
|
||||||
stanza, e := r.ReadStanza(false)
|
|
||||||
c.Assert(e, IsNil)
|
|
||||||
c.Assert(len(stanza["Provides"]), Equals, 586929)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ControlFileSuite) BenchmarkReadStanza(c *C) {
|
func (s *ControlFileSuite) BenchmarkReadStanza(c *C) {
|
||||||
for i := 0; i < c.N; i++ {
|
for i := 0; i < c.N; i++ {
|
||||||
reader := bytes.NewBufferString(controlFile)
|
reader := bytes.NewBufferString(controlFile)
|
||||||
|
|||||||
+11
-11
@@ -33,9 +33,9 @@ func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz
|
|||||||
existingNodes := map[string]bool{}
|
existingNodes := map[string]bool{}
|
||||||
|
|
||||||
err = collectionFactory.RemoteRepoCollection().ForEach(func(repo *RemoteRepo) error {
|
err = collectionFactory.RemoteRepoCollection().ForEach(func(repo *RemoteRepo) error {
|
||||||
e := collectionFactory.RemoteRepoCollection().LoadComplete(repo)
|
err := collectionFactory.RemoteRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.AddNode("aptly", repo.UUID, map[string]string{
|
graph.AddNode("aptly", repo.UUID, map[string]string{
|
||||||
@@ -55,9 +55,9 @@ func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = collectionFactory.LocalRepoCollection().ForEach(func(repo *LocalRepo) error {
|
err = collectionFactory.LocalRepoCollection().ForEach(func(repo *LocalRepo) error {
|
||||||
e := collectionFactory.LocalRepoCollection().LoadComplete(repo)
|
err := collectionFactory.LocalRepoCollection().LoadComplete(repo)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.AddNode("aptly", repo.UUID, map[string]string{
|
graph.AddNode("aptly", repo.UUID, map[string]string{
|
||||||
@@ -81,13 +81,13 @@ func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz
|
|||||||
})
|
})
|
||||||
|
|
||||||
err = collectionFactory.SnapshotCollection().ForEach(func(snapshot *Snapshot) error {
|
err = collectionFactory.SnapshotCollection().ForEach(func(snapshot *Snapshot) error {
|
||||||
e := collectionFactory.SnapshotCollection().LoadComplete(snapshot)
|
err := collectionFactory.SnapshotCollection().LoadComplete(snapshot)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return e
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
description := snapshot.Description
|
description := snapshot.Description
|
||||||
if snapshot.SourceKind == SourceRemoteRepo {
|
if snapshot.SourceKind == "repo" {
|
||||||
description = "Snapshot from repo"
|
description = "Snapshot from repo"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz
|
|||||||
snapshot.Name, description, snapshot.NumPackages(), labelEnd),
|
snapshot.Name, description, snapshot.NumPackages(), labelEnd),
|
||||||
})
|
})
|
||||||
|
|
||||||
if snapshot.SourceKind == SourceRemoteRepo || snapshot.SourceKind == SourceLocalRepo || snapshot.SourceKind == SourceSnapshot {
|
if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" {
|
||||||
for _, uuid := range snapshot.SourceIDs {
|
for _, uuid := range snapshot.SourceIDs {
|
||||||
_, exists := existingNodes[uuid]
|
_, exists := existingNodes[uuid]
|
||||||
if exists {
|
if exists {
|
||||||
|
|||||||
+18
-48
@@ -6,13 +6,12 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CollectPackageFiles walks filesystem collecting all candidates for package files
|
// CollectPackageFiles walks filesystem collecting all candidates for package files
|
||||||
func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (packageFiles, otherFiles, failedFiles []string) {
|
func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (packageFiles, failedFiles []string) {
|
||||||
for _, location := range locations {
|
for _, location := range locations {
|
||||||
info, err2 := os.Stat(location)
|
info, err2 := os.Stat(location)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
@@ -32,8 +31,6 @@ func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (pac
|
|||||||
if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") ||
|
if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") ||
|
||||||
strings.HasSuffix(info.Name(), ".dsc") || strings.HasSuffix(info.Name(), ".ddeb") {
|
strings.HasSuffix(info.Name(), ".dsc") || strings.HasSuffix(info.Name(), ".ddeb") {
|
||||||
packageFiles = append(packageFiles, path)
|
packageFiles = append(packageFiles, path)
|
||||||
} else if strings.HasSuffix(info.Name(), ".buildinfo") {
|
|
||||||
otherFiles = append(otherFiles, path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -48,8 +45,6 @@ func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (pac
|
|||||||
if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") ||
|
if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") ||
|
||||||
strings.HasSuffix(info.Name(), ".dsc") || strings.HasSuffix(info.Name(), ".ddeb") {
|
strings.HasSuffix(info.Name(), ".dsc") || strings.HasSuffix(info.Name(), ".ddeb") {
|
||||||
packageFiles = append(packageFiles, location)
|
packageFiles = append(packageFiles, location)
|
||||||
} else if strings.HasSuffix(info.Name(), ".buildinfo") {
|
|
||||||
otherFiles = append(otherFiles, location)
|
|
||||||
} else {
|
} else {
|
||||||
reporter.Warning("Unknown file extension: %s", location)
|
reporter.Warning("Unknown file extension: %s", location)
|
||||||
failedFiles = append(failedFiles, location)
|
failedFiles = append(failedFiles, location)
|
||||||
@@ -64,9 +59,8 @@ func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (pac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ImportPackageFiles imports files into local repository
|
// ImportPackageFiles imports files into local repository
|
||||||
func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace bool, verifier pgp.Verifier,
|
func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace bool, verifier utils.Verifier,
|
||||||
pool aptly.PackagePool, collection *PackageCollection, reporter aptly.ResultReporter, restriction PackageQuery,
|
pool aptly.PackagePool, collection *PackageCollection, reporter aptly.ResultReporter, restriction PackageQuery) (processedFiles []string, failedFiles []string, err error) {
|
||||||
checksumStorage aptly.ChecksumStorage) (processedFiles []string, failedFiles []string, err error) {
|
|
||||||
if forceReplace {
|
if forceReplace {
|
||||||
list.PrepareIndex()
|
list.PrepareIndex()
|
||||||
}
|
}
|
||||||
@@ -122,24 +116,19 @@ func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace b
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var files PackageFiles
|
|
||||||
|
|
||||||
if isSourcePackage {
|
|
||||||
files = p.Files()
|
|
||||||
}
|
|
||||||
|
|
||||||
var checksums utils.ChecksumInfo
|
var checksums utils.ChecksumInfo
|
||||||
checksums, err = utils.ChecksumsForFile(file)
|
checksums, err = utils.ChecksumsForFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mainPackageFile := PackageFile{
|
if isSourcePackage {
|
||||||
Filename: filepath.Base(file),
|
p.UpdateFiles(append(p.Files(), PackageFile{Filename: filepath.Base(file), Checksums: checksums}))
|
||||||
Checksums: checksums,
|
} else {
|
||||||
|
p.UpdateFiles([]PackageFile{{Filename: filepath.Base(file), Checksums: checksums}})
|
||||||
}
|
}
|
||||||
|
|
||||||
mainPackageFile.PoolPath, err = pool.Import(file, mainPackageFile.Filename, &mainPackageFile.Checksums, false, checksumStorage)
|
err = pool.Import(file, checksums.MD5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reporter.Warning("Unable to import file %s into pool: %s", file, err)
|
reporter.Warning("Unable to import file %s into pool: %s", file, err)
|
||||||
failedFiles = append(failedFiles, file)
|
failedFiles = append(failedFiles, file)
|
||||||
@@ -148,45 +137,26 @@ func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace b
|
|||||||
|
|
||||||
candidateProcessedFiles = append(candidateProcessedFiles, file)
|
candidateProcessedFiles = append(candidateProcessedFiles, file)
|
||||||
|
|
||||||
// go over all the other files
|
// go over all files, except for the last one (.dsc/.deb itself)
|
||||||
for i := range files {
|
for _, f := range p.Files() {
|
||||||
sourceFile := filepath.Join(filepath.Dir(file), filepath.Base(files[i].Filename))
|
if filepath.Base(f.Filename) == filepath.Base(file) {
|
||||||
|
continue
|
||||||
_, err = os.Stat(sourceFile)
|
|
||||||
if err == nil {
|
|
||||||
files[i].PoolPath, err = pool.Import(sourceFile, files[i].Filename, &files[i].Checksums, false, checksumStorage)
|
|
||||||
if err == nil {
|
|
||||||
candidateProcessedFiles = append(candidateProcessedFiles, sourceFile)
|
|
||||||
}
|
}
|
||||||
} else if os.IsNotExist(err) {
|
sourceFile := filepath.Join(filepath.Dir(file), filepath.Base(f.Filename))
|
||||||
// if file is not present, try to find it in the pool
|
err = pool.Import(sourceFile, f.Checksums.MD5)
|
||||||
var (
|
|
||||||
err2 error
|
|
||||||
found bool
|
|
||||||
)
|
|
||||||
|
|
||||||
files[i].PoolPath, found, err2 = pool.Verify("", files[i].Filename, &files[i].Checksums, checksumStorage)
|
|
||||||
if err2 != nil {
|
|
||||||
err = err2
|
|
||||||
} else if found {
|
|
||||||
// clear error, file is already in the package pool
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reporter.Warning("Unable to import file %s into pool: %s", sourceFile, err)
|
reporter.Warning("Unable to import file %s into pool: %s", sourceFile, err)
|
||||||
failedFiles = append(failedFiles, file)
|
failedFiles = append(failedFiles, file)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
candidateProcessedFiles = append(candidateProcessedFiles, sourceFile)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// some files haven't been imported
|
// some files haven't been imported
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
p.UpdateFiles(append(files, mainPackageFile))
|
|
||||||
|
|
||||||
if restriction != nil && !restriction.Matches(p) {
|
if restriction != nil && !restriction.Matches(p) {
|
||||||
reporter.Warning("%s has been ignored as it doesn't match restriction", p)
|
reporter.Warning("%s has been ignored as it doesn't match restriction", p)
|
||||||
failedFiles = append(failedFiles, file)
|
failedFiles = append(failedFiles, file)
|
||||||
|
|||||||
+10
-120
@@ -4,13 +4,11 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type indexFiles struct {
|
type indexFiles struct {
|
||||||
@@ -21,7 +19,6 @@ type indexFiles struct {
|
|||||||
tempDir string
|
tempDir string
|
||||||
suffix string
|
suffix string
|
||||||
indexes map[string]*indexFile
|
indexes map[string]*indexFile
|
||||||
acquireByHash bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type indexFile struct {
|
type indexFile struct {
|
||||||
@@ -30,7 +27,6 @@ type indexFile struct {
|
|||||||
compressable bool
|
compressable bool
|
||||||
onlyGzip bool
|
onlyGzip bool
|
||||||
signable bool
|
signable bool
|
||||||
acquireByHash bool
|
|
||||||
relativePath string
|
relativePath string
|
||||||
tempFilename string
|
tempFilename string
|
||||||
tempFile *os.File
|
tempFile *os.File
|
||||||
@@ -52,7 +48,7 @@ func (file *indexFile) BufWriter() (*bufio.Writer, error) {
|
|||||||
return file.w, nil
|
return file.w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *indexFile) Finalize(signer pgp.Signer) error {
|
func (file *indexFile) Finalize(signer utils.Signer) error {
|
||||||
if file.w == nil {
|
if file.w == nil {
|
||||||
if file.discardable {
|
if file.discardable {
|
||||||
return nil
|
return nil
|
||||||
@@ -94,22 +90,11 @@ func (file *indexFile) Finalize(signer pgp.Signer) error {
|
|||||||
file.parent.generatedFiles[file.relativePath+ext] = checksumInfo
|
file.parent.generatedFiles[file.relativePath+ext] = checksumInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
filedir := filepath.Dir(filepath.Join(file.parent.basePath, file.relativePath))
|
err = file.parent.publishedStorage.MkDir(filepath.Dir(filepath.Join(file.parent.basePath, file.relativePath)))
|
||||||
|
|
||||||
err = file.parent.publishedStorage.MkDir(filedir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create dir: %s", err)
|
return fmt.Errorf("unable to create dir: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.acquireByHash {
|
|
||||||
for _, hash := range []string{"MD5Sum", "SHA1", "SHA256", "SHA512"} {
|
|
||||||
err = file.parent.publishedStorage.MkDir(filepath.Join(filedir, "by-hash", hash))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to create dir: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ext := range exts {
|
for _, ext := range exts {
|
||||||
err = file.parent.publishedStorage.PutFile(filepath.Join(file.parent.basePath, file.relativePath+file.parent.suffix+ext),
|
err = file.parent.publishedStorage.PutFile(filepath.Join(file.parent.basePath, file.relativePath+file.parent.suffix+ext),
|
||||||
file.tempFilename+ext)
|
file.tempFilename+ext)
|
||||||
@@ -121,16 +106,6 @@ func (file *indexFile) Finalize(signer pgp.Signer) error {
|
|||||||
file.parent.renameMap[filepath.Join(file.parent.basePath, file.relativePath+file.parent.suffix+ext)] =
|
file.parent.renameMap[filepath.Join(file.parent.basePath, file.relativePath+file.parent.suffix+ext)] =
|
||||||
filepath.Join(file.parent.basePath, file.relativePath+ext)
|
filepath.Join(file.parent.basePath, file.relativePath+ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.acquireByHash {
|
|
||||||
sums := file.parent.generatedFiles[file.relativePath+ext]
|
|
||||||
for hash, sum := range map[string]string{"SHA512": sums.SHA512, "SHA256": sums.SHA256, "SHA1": sums.SHA1, "MD5Sum": sums.MD5} {
|
|
||||||
err = packageIndexByHash(file, ext, hash, sum)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to build hash file: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.signable && signer != nil {
|
if file.signable && signer != nil {
|
||||||
@@ -167,57 +142,7 @@ func (file *indexFile) Finalize(signer pgp.Signer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func packageIndexByHash(file *indexFile, ext string, hash string, sum string) error {
|
func newIndexFiles(publishedStorage aptly.PublishedStorage, basePath, tempDir, suffix string) *indexFiles {
|
||||||
src := filepath.Join(file.parent.basePath, file.relativePath)
|
|
||||||
indexfile := path.Base(src + ext)
|
|
||||||
src = src + file.parent.suffix + ext
|
|
||||||
filedir := filepath.Dir(filepath.Join(file.parent.basePath, file.relativePath))
|
|
||||||
dst := filepath.Join(filedir, "by-hash", hash)
|
|
||||||
sumfilePath := filepath.Join(dst, sum)
|
|
||||||
|
|
||||||
// link already exists? do nothing
|
|
||||||
exists, err := file.parent.publishedStorage.FileExists(sumfilePath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Acquire-By-Hash: error checking exists of file %s: %s", sumfilePath, err)
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the link
|
|
||||||
err = file.parent.publishedStorage.HardLink(src, sumfilePath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Acquire-By-Hash: error creating hardlink %s: %s", sumfilePath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a previous index file already exists exists, backup symlink
|
|
||||||
indexPath := filepath.Join(dst, indexfile)
|
|
||||||
oldIndexPath := filepath.Join(dst, indexfile+".old")
|
|
||||||
if exists, _ = file.parent.publishedStorage.FileExists(indexPath); exists {
|
|
||||||
// if exists, remove old symlink
|
|
||||||
if exists, _ = file.parent.publishedStorage.FileExists(oldIndexPath); exists {
|
|
||||||
var linkTarget string
|
|
||||||
linkTarget, err = file.parent.publishedStorage.ReadLink(oldIndexPath)
|
|
||||||
if err == nil {
|
|
||||||
// If we managed to resolve the link target: delete it. This is the
|
|
||||||
// oldest physical index file we no longer need. Once we drop our
|
|
||||||
// old symlink we'll essentially forget about it existing at all.
|
|
||||||
file.parent.publishedStorage.Remove(linkTarget)
|
|
||||||
}
|
|
||||||
file.parent.publishedStorage.Remove(oldIndexPath)
|
|
||||||
}
|
|
||||||
file.parent.publishedStorage.RenameFile(indexPath, oldIndexPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create symlink
|
|
||||||
err = file.parent.publishedStorage.SymLink(filepath.Join(dst, sum), filepath.Join(dst, indexfile))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Acquire-By-Hash: error creating symlink %s: %s", filepath.Join(dst, indexfile), err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newIndexFiles(publishedStorage aptly.PublishedStorage, basePath, tempDir, suffix string, acquireByHash bool) *indexFiles {
|
|
||||||
return &indexFiles{
|
return &indexFiles{
|
||||||
publishedStorage: publishedStorage,
|
publishedStorage: publishedStorage,
|
||||||
basePath: basePath,
|
basePath: basePath,
|
||||||
@@ -226,12 +151,11 @@ func newIndexFiles(publishedStorage aptly.PublishedStorage, basePath, tempDir, s
|
|||||||
tempDir: tempDir,
|
tempDir: tempDir,
|
||||||
suffix: suffix,
|
suffix: suffix,
|
||||||
indexes: make(map[string]*indexFile),
|
indexes: make(map[string]*indexFile),
|
||||||
acquireByHash: acquireByHash,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (files *indexFiles) PackageIndex(component, arch string, udeb bool) *indexFile {
|
func (files *indexFiles) PackageIndex(component, arch string, udeb bool) *indexFile {
|
||||||
if arch == ArchitectureSource {
|
if arch == "source" {
|
||||||
udeb = false
|
udeb = false
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("pi-%s-%s-%v", component, arch, udeb)
|
key := fmt.Sprintf("pi-%s-%s-%v", component, arch, udeb)
|
||||||
@@ -239,7 +163,7 @@ func (files *indexFiles) PackageIndex(component, arch string, udeb bool) *indexF
|
|||||||
if !ok {
|
if !ok {
|
||||||
var relativePath string
|
var relativePath string
|
||||||
|
|
||||||
if arch == ArchitectureSource {
|
if arch == "source" {
|
||||||
relativePath = filepath.Join(component, "source", "Sources")
|
relativePath = filepath.Join(component, "source", "Sources")
|
||||||
} else {
|
} else {
|
||||||
if udeb {
|
if udeb {
|
||||||
@@ -254,7 +178,6 @@ func (files *indexFiles) PackageIndex(component, arch string, udeb bool) *indexF
|
|||||||
discardable: false,
|
discardable: false,
|
||||||
compressable: true,
|
compressable: true,
|
||||||
signable: false,
|
signable: false,
|
||||||
acquireByHash: files.acquireByHash,
|
|
||||||
relativePath: relativePath,
|
relativePath: relativePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +188,7 @@ func (files *indexFiles) PackageIndex(component, arch string, udeb bool) *indexF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (files *indexFiles) ReleaseIndex(component, arch string, udeb bool) *indexFile {
|
func (files *indexFiles) ReleaseIndex(component, arch string, udeb bool) *indexFile {
|
||||||
if arch == ArchitectureSource {
|
if arch == "source" {
|
||||||
udeb = false
|
udeb = false
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("ri-%s-%s-%v", component, arch, udeb)
|
key := fmt.Sprintf("ri-%s-%s-%v", component, arch, udeb)
|
||||||
@@ -273,7 +196,7 @@ func (files *indexFiles) ReleaseIndex(component, arch string, udeb bool) *indexF
|
|||||||
if !ok {
|
if !ok {
|
||||||
var relativePath string
|
var relativePath string
|
||||||
|
|
||||||
if arch == ArchitectureSource {
|
if arch == "source" {
|
||||||
relativePath = filepath.Join(component, "source", "Release")
|
relativePath = filepath.Join(component, "source", "Release")
|
||||||
} else {
|
} else {
|
||||||
if udeb {
|
if udeb {
|
||||||
@@ -288,7 +211,6 @@ func (files *indexFiles) ReleaseIndex(component, arch string, udeb bool) *indexF
|
|||||||
discardable: udeb,
|
discardable: udeb,
|
||||||
compressable: false,
|
compressable: false,
|
||||||
signable: false,
|
signable: false,
|
||||||
acquireByHash: files.acquireByHash,
|
|
||||||
relativePath: relativePath,
|
relativePath: relativePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +221,7 @@ func (files *indexFiles) ReleaseIndex(component, arch string, udeb bool) *indexF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (files *indexFiles) ContentsIndex(component, arch string, udeb bool) *indexFile {
|
func (files *indexFiles) ContentsIndex(component, arch string, udeb bool) *indexFile {
|
||||||
if arch == ArchitectureSource {
|
if arch == "source" {
|
||||||
udeb = false
|
udeb = false
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("ci-%s-%s-%v", component, arch, udeb)
|
key := fmt.Sprintf("ci-%s-%s-%v", component, arch, udeb)
|
||||||
@@ -319,38 +241,6 @@ func (files *indexFiles) ContentsIndex(component, arch string, udeb bool) *index
|
|||||||
compressable: true,
|
compressable: true,
|
||||||
onlyGzip: true,
|
onlyGzip: true,
|
||||||
signable: false,
|
signable: false,
|
||||||
acquireByHash: files.acquireByHash,
|
|
||||||
relativePath: relativePath,
|
|
||||||
}
|
|
||||||
|
|
||||||
files.indexes[key] = file
|
|
||||||
}
|
|
||||||
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
func (files *indexFiles) LegacyContentsIndex(arch string, udeb bool) *indexFile {
|
|
||||||
if arch == ArchitectureSource {
|
|
||||||
udeb = false
|
|
||||||
}
|
|
||||||
key := fmt.Sprintf("lci-%s-%v", arch, udeb)
|
|
||||||
file, ok := files.indexes[key]
|
|
||||||
if !ok {
|
|
||||||
var relativePath string
|
|
||||||
|
|
||||||
if udeb {
|
|
||||||
relativePath = fmt.Sprintf("Contents-udeb-%s", arch)
|
|
||||||
} else {
|
|
||||||
relativePath = fmt.Sprintf("Contents-%s", arch)
|
|
||||||
}
|
|
||||||
|
|
||||||
file = &indexFile{
|
|
||||||
parent: files,
|
|
||||||
discardable: true,
|
|
||||||
compressable: true,
|
|
||||||
onlyGzip: true,
|
|
||||||
signable: false,
|
|
||||||
acquireByHash: files.acquireByHash,
|
|
||||||
relativePath: relativePath,
|
relativePath: relativePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-64
@@ -3,10 +3,9 @@ package deb
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dependency options
|
// Dependency options
|
||||||
@@ -21,8 +20,6 @@ const (
|
|||||||
DepFollowAllVariants
|
DepFollowAllVariants
|
||||||
// DepFollowBuild pulls build dependencies
|
// DepFollowBuild pulls build dependencies
|
||||||
DepFollowBuild
|
DepFollowBuild
|
||||||
// DepVerboseResolve emits additional logs while dependencies are being resolved
|
|
||||||
DepVerboseResolve
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageList is list of unique (by key) packages
|
// PackageList is list of unique (by key) packages
|
||||||
@@ -34,6 +31,8 @@ const (
|
|||||||
type PackageList struct {
|
type PackageList struct {
|
||||||
// Straight list of packages as map
|
// Straight list of packages as map
|
||||||
packages map[string]*Package
|
packages map[string]*Package
|
||||||
|
// Has index been prepared?
|
||||||
|
indexed bool
|
||||||
// Indexed list of packages, sorted by name internally
|
// Indexed list of packages, sorted by name internally
|
||||||
packagesIndex []*Package
|
packagesIndex []*Package
|
||||||
// Map of packages for each virtual package (provides)
|
// Map of packages for each virtual package (provides)
|
||||||
@@ -42,8 +41,6 @@ type PackageList struct {
|
|||||||
keyFunc func(p *Package) string
|
keyFunc func(p *Package) string
|
||||||
// Allow duplicates?
|
// Allow duplicates?
|
||||||
duplicatesAllowed bool
|
duplicatesAllowed bool
|
||||||
// Has index been prepared?
|
|
||||||
indexed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageConflictError means that package can't be added to the list due to error
|
// PackageConflictError means that package can't be added to the list due to error
|
||||||
@@ -124,14 +121,6 @@ func NewPackageListFromRefList(reflist *PackageRefList, collection *PackageColle
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has checks whether package is already in the list
|
|
||||||
func (l *PackageList) Has(p *Package) bool {
|
|
||||||
key := l.keyFunc(p)
|
|
||||||
_, ok := l.packages[key]
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add appends package to package list, additionally checking for uniqueness
|
// Add appends package to package list, additionally checking for uniqueness
|
||||||
func (l *PackageList) Add(p *Package) error {
|
func (l *PackageList) Add(p *Package) error {
|
||||||
key := l.keyFunc(p)
|
key := l.keyFunc(p)
|
||||||
@@ -246,7 +235,7 @@ func (l *PackageList) Remove(p *Package) {
|
|||||||
func (l *PackageList) Architectures(includeSource bool) (result []string) {
|
func (l *PackageList) Architectures(includeSource bool) (result []string) {
|
||||||
result = make([]string, 0, 10)
|
result = make([]string, 0, 10)
|
||||||
for _, pkg := range l.packages {
|
for _, pkg := range l.packages {
|
||||||
if pkg.Architecture != ArchitectureAll && (pkg.Architecture != ArchitectureSource || includeSource) && !utils.StrSliceHasItem(result, pkg.Architecture) {
|
if pkg.Architecture != "all" && (pkg.Architecture != "source" || includeSource) && !utils.StrSliceHasItem(result, pkg.Architecture) {
|
||||||
result = append(result, pkg.Architecture)
|
result = append(result, pkg.Architecture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,14 +346,6 @@ func (l *PackageList) VerifyDependencies(options int, architectures []string, so
|
|||||||
progress.ShutdownBar()
|
progress.ShutdownBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
if options&DepVerboseResolve == DepVerboseResolve && progress != nil {
|
|
||||||
missingStr := make([]string, len(missing))
|
|
||||||
for i := range missing {
|
|
||||||
missingStr[i] = missing[i].String()
|
|
||||||
}
|
|
||||||
progress.ColoredPrintf("@{y}Missing dependencies:@| %s", strings.Join(missingStr, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
return missing, nil
|
return missing, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +430,18 @@ func (l *PackageList) Search(dep Dependency, allMatches bool) (searchResults []*
|
|||||||
panic("list not indexed, can't search")
|
panic("list not indexed, can't search")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dep.Relation == VersionDontCare {
|
||||||
|
for _, p := range l.providesIndex[dep.Pkg] {
|
||||||
|
if dep.Architecture == "" || p.MatchesArchitecture(dep.Architecture) {
|
||||||
|
searchResults = append(searchResults, p)
|
||||||
|
|
||||||
|
if !allMatches {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg })
|
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg })
|
||||||
|
|
||||||
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
||||||
@@ -464,28 +457,11 @@ func (l *PackageList) Search(dep Dependency, allMatches bool) (searchResults []*
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
if dep.Relation == VersionDontCare {
|
|
||||||
for _, p := range l.providesIndex[dep.Pkg] {
|
|
||||||
if dep.Architecture == "" || p.MatchesArchitecture(dep.Architecture) {
|
|
||||||
searchResults = append(searchResults, p)
|
|
||||||
|
|
||||||
if !allMatches {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
|
// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
|
||||||
func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) {
|
func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) {
|
||||||
return l.FilterWithProgress(queries, withDependencies, source, dependencyOptions, architecturesList, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterWithProgress filters package index by specified queries (ORed together), possibly pulling dependencies and displays progress
|
|
||||||
func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string, progress aptly.Progress) (*PackageList, error) {
|
|
||||||
if !l.indexed {
|
if !l.indexed {
|
||||||
panic("list not indexed, can't filter")
|
panic("list not indexed, can't filter")
|
||||||
}
|
}
|
||||||
@@ -512,37 +488,22 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie
|
|||||||
added = 0
|
added = 0
|
||||||
|
|
||||||
// find missing dependencies
|
// find missing dependencies
|
||||||
missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, progress)
|
missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to satisfy dependencies
|
// try to satisfy dependencies
|
||||||
for _, dep := range missing {
|
for _, dep := range missing {
|
||||||
if dependencyOptions&DepFollowAllVariants == 0 {
|
|
||||||
// dependency might have already been satisfied
|
// dependency might have already been satisfied
|
||||||
// with packages already been added
|
// with packages already been added
|
||||||
//
|
|
||||||
// when follow-all-variants is enabled, we need to try to expand anyway,
|
|
||||||
// as even if dependency is satisfied now, there might be other ways to satisfy dependency
|
|
||||||
if result.Search(dep, false) != nil {
|
if result.Search(dep, false) != nil {
|
||||||
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
|
|
||||||
progress.ColoredPrintf("@{y}Already satisfied dependency@|: %s with %s", &dep, result.Search(dep, true))
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
searchResults := l.Search(dep, true)
|
searchResults := l.Search(dep, false)
|
||||||
if len(searchResults) > 0 {
|
if searchResults != nil {
|
||||||
for _, p := range searchResults {
|
for _, p := range searchResults {
|
||||||
if result.Has(p) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
|
|
||||||
progress.ColoredPrintf("@{g}Injecting package@|: %s", p)
|
|
||||||
}
|
|
||||||
result.Add(p)
|
result.Add(p)
|
||||||
dependencySource.Add(p)
|
dependencySource.Add(p)
|
||||||
added++
|
added++
|
||||||
@@ -550,11 +511,6 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
|
|
||||||
progress.ColoredPrintf("@{r}Unsatisfied dependency@|: %s", dep.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/aptly-dev/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"
|
||||||
)
|
)
|
||||||
|
|||||||
+7
-7
@@ -3,7 +3,7 @@ package deb
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
@@ -18,7 +18,7 @@ type LocalRepoSuite struct {
|
|||||||
var _ = Suite(&LocalRepoSuite{})
|
var _ = Suite(&LocalRepoSuite{})
|
||||||
|
|
||||||
func (s *LocalRepoSuite) SetUpTest(c *C) {
|
func (s *LocalRepoSuite) SetUpTest(c *C) {
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.list = NewPackageList()
|
s.list = NewPackageList()
|
||||||
s.list.Add(&Package{Name: "lib", Version: "1.7", Architecture: "i386"})
|
s.list.Add(&Package{Name: "lib", Version: "1.7", Architecture: "i386"})
|
||||||
s.list.Add(&Package{Name: "app", Version: "1.9", Architecture: "amd64"})
|
s.list.Add(&Package{Name: "app", Version: "1.9", Architecture: "amd64"})
|
||||||
@@ -83,7 +83,7 @@ type LocalRepoCollectionSuite struct {
|
|||||||
var _ = Suite(&LocalRepoCollectionSuite{})
|
var _ = Suite(&LocalRepoCollectionSuite{})
|
||||||
|
|
||||||
func (s *LocalRepoCollectionSuite) SetUpTest(c *C) {
|
func (s *LocalRepoCollectionSuite) SetUpTest(c *C) {
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.collection = NewLocalRepoCollection(s.db)
|
s.collection = NewLocalRepoCollection(s.db)
|
||||||
|
|
||||||
s.list = NewPackageList()
|
s.list = NewPackageList()
|
||||||
@@ -98,14 +98,14 @@ func (s *LocalRepoCollectionSuite) TearDownTest(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalRepoCollectionSuite) TestAddByName(c *C) {
|
func (s *LocalRepoCollectionSuite) TestAddByName(c *C) {
|
||||||
_, err := s.collection.ByName("local1")
|
r, err := s.collection.ByName("local1")
|
||||||
c.Assert(err, ErrorMatches, "*.not found")
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
repo := NewLocalRepo("local1", "Comment 1")
|
repo := NewLocalRepo("local1", "Comment 1")
|
||||||
c.Assert(s.collection.Add(repo), IsNil)
|
c.Assert(s.collection.Add(repo), IsNil)
|
||||||
c.Assert(s.collection.Add(repo), ErrorMatches, ".*already exists")
|
c.Assert(s.collection.Add(repo), ErrorMatches, ".*already exists")
|
||||||
|
|
||||||
r, err := s.collection.ByName("local1")
|
r, err = s.collection.ByName("local1")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(r.String(), Equals, repo.String())
|
c.Assert(r.String(), Equals, repo.String())
|
||||||
|
|
||||||
@@ -116,13 +116,13 @@ func (s *LocalRepoCollectionSuite) TestAddByName(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalRepoCollectionSuite) TestByUUID(c *C) {
|
func (s *LocalRepoCollectionSuite) TestByUUID(c *C) {
|
||||||
_, err := s.collection.ByUUID("some-uuid")
|
r, err := s.collection.ByUUID("some-uuid")
|
||||||
c.Assert(err, ErrorMatches, "*.not found")
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
repo := NewLocalRepo("local1", "Comment 1")
|
repo := NewLocalRepo("local1", "Comment 1")
|
||||||
c.Assert(s.collection.Add(repo), IsNil)
|
c.Assert(s.collection.Add(repo), IsNil)
|
||||||
|
|
||||||
r, err := s.collection.ByUUID(repo.UUID)
|
r, err = s.collection.ByUUID(repo.UUID)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(r.String(), Equals, repo.String())
|
c.Assert(r.String(), Equals, repo.String())
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+35
-61
@@ -7,8 +7,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Package is single instance of Debian package
|
// Package is single instance of Debian package
|
||||||
@@ -24,12 +24,12 @@ type Package struct {
|
|||||||
Source string
|
Source string
|
||||||
// List of virtual packages this package provides
|
// List of virtual packages this package provides
|
||||||
Provides []string
|
Provides []string
|
||||||
// Hash of files section
|
|
||||||
FilesHash uint64
|
|
||||||
// Is this source package
|
// Is this source package
|
||||||
IsSource bool
|
IsSource bool
|
||||||
// Is this udeb package
|
// Is this udeb package
|
||||||
IsUdeb bool
|
IsUdeb bool
|
||||||
|
// Hash of files section
|
||||||
|
FilesHash uint64
|
||||||
// Is this >= 0.6 package?
|
// Is this >= 0.6 package?
|
||||||
V06Plus bool
|
V06Plus bool
|
||||||
// Offload fields
|
// Offload fields
|
||||||
@@ -41,20 +41,6 @@ type Package struct {
|
|||||||
collection *PackageCollection
|
collection *PackageCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package types
|
|
||||||
const (
|
|
||||||
PackageTypeBinary = "deb"
|
|
||||||
PackageTypeUdeb = "udeb"
|
|
||||||
PackageTypeSource = "source"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Special arhictectures
|
|
||||||
const (
|
|
||||||
ArchitectureAll = "all"
|
|
||||||
ArhictectureAny = "any"
|
|
||||||
ArchitectureSource = "source"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Check interface
|
// Check interface
|
||||||
var (
|
var (
|
||||||
_ json.Marshaler = &Package{}
|
_ json.Marshaler = &Package{}
|
||||||
@@ -232,12 +218,12 @@ func (p *Package) GetField(name string) string {
|
|||||||
return p.Architecture
|
return p.Architecture
|
||||||
case "$PackageType":
|
case "$PackageType":
|
||||||
if p.IsSource {
|
if p.IsSource {
|
||||||
return PackageTypeSource
|
return "source"
|
||||||
}
|
}
|
||||||
if p.IsUdeb {
|
if p.IsUdeb {
|
||||||
return PackageTypeUdeb
|
return "udeb"
|
||||||
}
|
}
|
||||||
return PackageTypeBinary
|
return "deb"
|
||||||
case "Name":
|
case "Name":
|
||||||
return p.Name
|
return p.Name
|
||||||
case "Version":
|
case "Version":
|
||||||
@@ -270,7 +256,7 @@ func (p *Package) GetField(name string) string {
|
|||||||
|
|
||||||
// MatchesArchitecture checks whether packages matches specified architecture
|
// MatchesArchitecture checks whether packages matches specified architecture
|
||||||
func (p *Package) MatchesArchitecture(arch string) bool {
|
func (p *Package) MatchesArchitecture(arch string) bool {
|
||||||
if p.Architecture == ArchitectureAll && arch != ArchitectureSource {
|
if p.Architecture == "all" && arch != "source" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +344,7 @@ func (p *Package) GetDependencies(options int) (dependencies []string) {
|
|||||||
if source == "" {
|
if source == "" {
|
||||||
source = p.Name
|
source = p.Name
|
||||||
}
|
}
|
||||||
if strings.Contains(source, ")") {
|
if strings.Index(source, ")") != -1 {
|
||||||
dependencies = append(dependencies, fmt.Sprintf("%s {source}", source))
|
dependencies = append(dependencies, fmt.Sprintf("%s {source}", source))
|
||||||
} else {
|
} else {
|
||||||
dependencies = append(dependencies, fmt.Sprintf("%s (= %s) {source}", source, p.Version))
|
dependencies = append(dependencies, fmt.Sprintf("%s (= %s) {source}", source, p.Version))
|
||||||
@@ -417,47 +403,32 @@ func (p *Package) Files() PackageFiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Contents returns cached package contents
|
// Contents returns cached package contents
|
||||||
func (p *Package) Contents(packagePool aptly.PackagePool, progress aptly.Progress) []string {
|
func (p *Package) Contents(packagePool aptly.PackagePool) []string {
|
||||||
if p.IsSource {
|
if p.IsSource {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.collection.loadContents(p, packagePool, progress)
|
return p.collection.loadContents(p, packagePool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalculateContents looks up contents in package file
|
// CalculateContents looks up contents in package file
|
||||||
func (p *Package) CalculateContents(packagePool aptly.PackagePool, progress aptly.Progress) ([]string, error) {
|
func (p *Package) CalculateContents(packagePool aptly.PackagePool) []string {
|
||||||
if p.IsSource {
|
if p.IsSource {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
file := p.Files()[0]
|
file := p.Files()[0]
|
||||||
poolPath, err := file.GetPoolPath(packagePool)
|
path, err := packagePool.Path(file.Filename, file.Checksums.MD5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if progress != nil {
|
panic(err)
|
||||||
progress.ColoredPrintf("@y[!]@| @!Failed to build pool path: @| %s", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, err := packagePool.Open(poolPath)
|
contents, err := GetContentsFromDeb(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if progress != nil {
|
panic(err)
|
||||||
progress.ColoredPrintf("@y[!]@| @!Failed to open package in pool: @| %s", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer reader.Close()
|
|
||||||
|
|
||||||
contents, err := GetContentsFromDeb(reader, file.Filename)
|
|
||||||
if err != nil {
|
|
||||||
if progress != nil {
|
|
||||||
progress.ColoredPrintf("@y[!]@| @!Failed to generate package contents: @| %s", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return contents, nil
|
return contents
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFiles saves new state of files
|
// UpdateFiles saves new state of files
|
||||||
@@ -570,7 +541,7 @@ func (p *Package) LinkFromPool(publishedStorage aptly.PublishedStorage, packageP
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, f := range p.Files() {
|
for i, f := range p.Files() {
|
||||||
sourcePoolPath, err := f.GetPoolPath(packagePool)
|
sourcePath, err := packagePool.Path(f.Filename, f.Checksums.MD5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -578,7 +549,7 @@ func (p *Package) LinkFromPool(publishedStorage aptly.PublishedStorage, packageP
|
|||||||
relPath := filepath.Join("pool", component, poolDir)
|
relPath := filepath.Join("pool", component, poolDir)
|
||||||
publishedDirectory := filepath.Join(prefix, relPath)
|
publishedDirectory := filepath.Join(prefix, relPath)
|
||||||
|
|
||||||
err = publishedStorage.LinkFromPool(publishedDirectory, f.Filename, packagePool, sourcePoolPath, f.Checksums, force)
|
err = publishedStorage.LinkFromPool(publishedDirectory, packagePool, sourcePath, f.Checksums.MD5, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -619,26 +590,29 @@ func (p *Package) PoolDirectory() (string, error) {
|
|||||||
|
|
||||||
// PackageDownloadTask is a element of download queue for the package
|
// PackageDownloadTask is a element of download queue for the package
|
||||||
type PackageDownloadTask struct {
|
type PackageDownloadTask struct {
|
||||||
File *PackageFile
|
RepoURI string
|
||||||
Additional []PackageDownloadTask
|
DestinationPath string
|
||||||
TempDownPath string
|
Checksums utils.ChecksumInfo
|
||||||
Done bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadList returns list of missing package files for download in format
|
// DownloadList returns list of missing package files for download in format
|
||||||
// [[srcpath, dstpath]]
|
// [[srcpath, dstpath]]
|
||||||
func (p *Package) DownloadList(packagePool aptly.PackagePool, checksumStorage aptly.ChecksumStorage) (result []PackageDownloadTask, err error) {
|
func (p *Package) DownloadList(packagePool aptly.PackagePool) (result []PackageDownloadTask, err error) {
|
||||||
result = make([]PackageDownloadTask, 0, 1)
|
result = make([]PackageDownloadTask, 0, 1)
|
||||||
|
|
||||||
files := p.Files()
|
for _, f := range p.Files() {
|
||||||
for idx := range files {
|
poolPath, err := packagePool.Path(f.Filename, f.Checksums.MD5)
|
||||||
verified, err := files[idx].Verify(packagePool, checksumStorage)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
verified, err := f.Verify(packagePool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !verified {
|
if !verified {
|
||||||
result = append(result, PackageDownloadTask{File: &files[idx]})
|
result = append(result, PackageDownloadTask{RepoURI: f.DownloadURL(), DestinationPath: poolPath, Checksums: f.Checksums})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,11 +620,11 @@ func (p *Package) DownloadList(packagePool aptly.PackagePool, checksumStorage ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyFiles verifies that all package files have neen correctly downloaded
|
// VerifyFiles verifies that all package files have neen correctly downloaded
|
||||||
func (p *Package) VerifyFiles(packagePool aptly.PackagePool, checksumStorage aptly.ChecksumStorage) (result bool, err error) {
|
func (p *Package) VerifyFiles(packagePool aptly.PackagePool) (result bool, err error) {
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
for _, f := range p.Files() {
|
for _, f := range p.Files() {
|
||||||
result, err = f.Verify(packagePool, checksumStorage)
|
result, err = f.Verify(packagePool)
|
||||||
if err != nil || !result {
|
if err != nil || !result {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -665,7 +639,7 @@ func (p *Package) FilepathList(packagePool aptly.PackagePool) ([]string, error)
|
|||||||
result := make([]string, len(p.Files()))
|
result := make([]string, len(p.Files()))
|
||||||
|
|
||||||
for i, f := range p.Files() {
|
for i, f := range p.Files() {
|
||||||
result[i], err = f.GetPoolPath(packagePool)
|
result[i], err = packagePool.RelativePath(f.Filename, f.Checksums.MD5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ func (collection *PackageCollection) loadFiles(p *Package) *PackageFiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loadContents loads or calculates and saves package contents
|
// loadContents loads or calculates and saves package contents
|
||||||
func (collection *PackageCollection) loadContents(p *Package, packagePool aptly.PackagePool, progress aptly.Progress) []string {
|
func (collection *PackageCollection) loadContents(p *Package, packagePool aptly.PackagePool) []string {
|
||||||
encoded, err := collection.db.Get(p.Key("xC"))
|
encoded, err := collection.db.Get(p.Key("xC"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
contents := []string{}
|
contents := []string{}
|
||||||
@@ -181,11 +181,7 @@ func (collection *PackageCollection) loadContents(p *Package, packagePool aptly.
|
|||||||
panic("unable to load contents")
|
panic("unable to load contents")
|
||||||
}
|
}
|
||||||
|
|
||||||
contents, err := p.CalculateContents(packagePool, progress)
|
contents := p.CalculateContents(packagePool)
|
||||||
if err != nil {
|
|
||||||
// failed to acquire contents, don't persist it
|
|
||||||
return contents
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err = codec.NewEncoder(&buf, collection.codecHandle).Encode(contents)
|
err = codec.NewEncoder(&buf, collection.codecHandle).Encode(contents)
|
||||||
@@ -315,7 +311,7 @@ func (collection *PackageCollection) SearchSupported() bool {
|
|||||||
|
|
||||||
// SearchByKey finds package by exact key
|
// SearchByKey finds package by exact key
|
||||||
func (collection *PackageCollection) SearchByKey(arch, name, version string) (result *PackageList) {
|
func (collection *PackageCollection) SearchByKey(arch, name, version string) (result *PackageList) {
|
||||||
result = NewPackageListWithDuplicates(true, 0)
|
result = NewPackageList()
|
||||||
|
|
||||||
for _, key := range collection.db.KeysByPrefix([]byte(fmt.Sprintf("P%s %s %s", arch, name, version))) {
|
for _, key := range collection.db.KeysByPrefix([]byte(fmt.Sprintf("P%s %s %s", arch, name, version))) {
|
||||||
pkg, err := collection.ByKey(key)
|
pkg, err := collection.ByKey(key)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package deb
|
package deb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
@@ -17,7 +17,7 @@ var _ = Suite(&PackageCollectionSuite{})
|
|||||||
|
|
||||||
func (s *PackageCollectionSuite) SetUpTest(c *C) {
|
func (s *PackageCollectionSuite) SetUpTest(c *C) {
|
||||||
s.p = NewPackageFromControlFile(packageStanza.Copy())
|
s.p = NewPackageFromControlFile(packageStanza.Copy())
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.collection = NewPackageCollection(s.db)
|
s.collection = NewPackageCollection(s.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-20
@@ -4,13 +4,14 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageFile is a single file entry in package
|
// PackageFile is a single file entry in package
|
||||||
@@ -19,33 +20,25 @@ type PackageFile struct {
|
|||||||
Filename string
|
Filename string
|
||||||
// Hashes for the file
|
// Hashes for the file
|
||||||
Checksums utils.ChecksumInfo
|
Checksums utils.ChecksumInfo
|
||||||
// PoolPath persists relative path to file in the package pool
|
|
||||||
PoolPath string
|
|
||||||
// Temporary field used while downloading, stored relative path on the mirror
|
// Temporary field used while downloading, stored relative path on the mirror
|
||||||
downloadPath string
|
downloadPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that package file is present and correct
|
// Verify that package file is present and correct
|
||||||
func (f *PackageFile) Verify(packagePool aptly.PackagePool, checksumStorage aptly.ChecksumStorage) (bool, error) {
|
func (f *PackageFile) Verify(packagePool aptly.PackagePool) (bool, error) {
|
||||||
generatedPoolPath, exists, err := packagePool.Verify(f.PoolPath, f.Filename, &f.Checksums, checksumStorage)
|
poolPath, err := packagePool.Path(f.Filename, f.Checksums.MD5)
|
||||||
if exists && err == nil {
|
if err != nil {
|
||||||
f.PoolPath = generatedPoolPath
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return exists, err
|
st, err := os.Stat(poolPath)
|
||||||
}
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
// GetPoolPath returns path to the file in the pool
|
|
||||||
//
|
|
||||||
// For legacy packages which do not have PoolPath field set, that calculates LegacyPath via pool
|
|
||||||
func (f *PackageFile) GetPoolPath(packagePool aptly.PackagePool) (string, error) {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if f.PoolPath == "" {
|
|
||||||
f.PoolPath, err = packagePool.LegacyPath(f.Filename, &f.Checksums)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.PoolPath, err
|
// verify size
|
||||||
|
// TODO: verify checksum if configured
|
||||||
|
return st.Size() == f.Checksums.Size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadURL return relative URL to package download location
|
// DownloadURL return relative URL to package download location
|
||||||
|
|||||||
+14
-14
@@ -1,25 +1,22 @@
|
|||||||
package deb
|
package deb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/files"
|
||||||
"github.com/aptly-dev/aptly/files"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PackageFilesSuite struct {
|
type PackageFilesSuite struct {
|
||||||
files PackageFiles
|
files PackageFiles
|
||||||
cs aptly.ChecksumStorage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&PackageFilesSuite{})
|
var _ = Suite(&PackageFilesSuite{})
|
||||||
|
|
||||||
func (s *PackageFilesSuite) SetUpTest(c *C) {
|
func (s *PackageFilesSuite) SetUpTest(c *C) {
|
||||||
s.cs = files.NewMockChecksumStorage()
|
|
||||||
s.files = PackageFiles{PackageFile{
|
s.files = PackageFiles{PackageFile{
|
||||||
Filename: "alien-arena-common_7.40-2_i386.deb",
|
Filename: "alien-arena-common_7.40-2_i386.deb",
|
||||||
downloadPath: "pool/contrib/a/alien-arena",
|
downloadPath: "pool/contrib/a/alien-arena",
|
||||||
@@ -32,24 +29,27 @@ func (s *PackageFilesSuite) SetUpTest(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageFilesSuite) TestVerify(c *C) {
|
func (s *PackageFilesSuite) TestVerify(c *C) {
|
||||||
packagePool := files.NewPackagePool(c.MkDir(), false)
|
packagePool := files.NewPackagePool(c.MkDir())
|
||||||
|
poolPath, _ := packagePool.Path(s.files[0].Filename, s.files[0].Checksums.MD5)
|
||||||
|
|
||||||
result, err := s.files[0].Verify(packagePool, s.cs)
|
result, err := s.files[0].Verify(packagePool)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(result, Equals, false)
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
tmpFilepath := filepath.Join(c.MkDir(), "file")
|
err = os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
c.Assert(ioutil.WriteFile(tmpFilepath, []byte("abcde"), 0777), IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
s.files[0].PoolPath, _ = packagePool.Import(tmpFilepath, s.files[0].Filename, &s.files[0].Checksums, false, s.cs)
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.WriteString("abcde")
|
||||||
|
file.Close()
|
||||||
|
|
||||||
s.files[0].Checksums.Size = 187518
|
result, err = s.files[0].Verify(packagePool)
|
||||||
result, err = s.files[0].Verify(packagePool, s.cs)
|
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(result, Equals, false)
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
s.files[0].Checksums.Size = 5
|
s.files[0].Checksums.Size = 5
|
||||||
result, err = s.files[0].Verify(packagePool, s.cs)
|
result, err = s.files[0].Verify(packagePool)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(result, Equals, true)
|
c.Check(result, Equals, true)
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-29
@@ -2,11 +2,12 @@ package deb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/files"
|
"github.com/smira/aptly/files"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
@@ -299,7 +300,7 @@ func (s *PackageSuite) TestMatchesDependency(c *C) {
|
|||||||
// ~
|
// ~
|
||||||
c.Check(
|
c.Check(
|
||||||
p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionRegexp, Version: "7\\.40-.*",
|
p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionRegexp, Version: "7\\.40-.*",
|
||||||
Regexp: regexp.MustCompile(`7\.40-.*`)}), Equals, true)
|
Regexp: regexp.MustCompile("7\\.40-.*")}), Equals, true)
|
||||||
c.Check(
|
c.Check(
|
||||||
p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionRegexp, Version: "7\\.40-.*",
|
p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionRegexp, Version: "7\\.40-.*",
|
||||||
Regexp: regexp.MustCompile("40")}), Equals, true)
|
Regexp: regexp.MustCompile("40")}), Equals, true)
|
||||||
@@ -362,17 +363,19 @@ func (s *PackageSuite) TestPoolDirectory(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestLinkFromPool(c *C) {
|
func (s *PackageSuite) TestLinkFromPool(c *C) {
|
||||||
packagePool := files.NewPackagePool(c.MkDir(), false)
|
packagePool := files.NewPackagePool(c.MkDir())
|
||||||
cs := files.NewMockChecksumStorage()
|
publishedStorage := files.NewPublishedStorage(c.MkDir())
|
||||||
publishedStorage := files.NewPublishedStorage(c.MkDir(), "", "")
|
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
tmpFilepath := filepath.Join(c.MkDir(), "file")
|
poolPath, _ := packagePool.Path(p.Files()[0].Filename, p.Files()[0].Checksums.MD5)
|
||||||
c.Assert(ioutil.WriteFile(tmpFilepath, nil, 0777), IsNil)
|
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
p.Files()[0].PoolPath, _ = packagePool.Import(tmpFilepath, p.Files()[0].Filename, &p.Files()[0].Checksums, false, cs)
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.Close()
|
||||||
|
|
||||||
err := p.LinkFromPool(publishedStorage, packagePool, "", "non-free", false)
|
err = p.LinkFromPool(publishedStorage, packagePool, "", "non-free", false)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(p.Files()[0].Filename, Equals, "alien-arena-common_7.40-2_i386.deb")
|
c.Check(p.Files()[0].Filename, Equals, "alien-arena-common_7.40-2_i386.deb")
|
||||||
c.Check(p.Files()[0].downloadPath, Equals, "pool/non-free/a/alien-arena")
|
c.Check(p.Files()[0].downloadPath, Equals, "pool/non-free/a/alien-arena")
|
||||||
@@ -384,7 +387,7 @@ func (s *PackageSuite) TestLinkFromPool(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestFilepathList(c *C) {
|
func (s *PackageSuite) TestFilepathList(c *C) {
|
||||||
packagePool := files.NewPackagePool(c.MkDir(), true)
|
packagePool := files.NewPackagePool(c.MkDir())
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
list, err := p.FilepathList(packagePool)
|
list, err := p.FilepathList(packagePool)
|
||||||
@@ -393,24 +396,31 @@ func (s *PackageSuite) TestFilepathList(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestDownloadList(c *C) {
|
func (s *PackageSuite) TestDownloadList(c *C) {
|
||||||
packagePool := files.NewPackagePool(c.MkDir(), false)
|
packagePool := files.NewPackagePool(c.MkDir())
|
||||||
cs := files.NewMockChecksumStorage()
|
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
p.Files()[0].Checksums.Size = 5
|
p.Files()[0].Checksums.Size = 5
|
||||||
|
poolPath, _ := packagePool.Path(p.Files()[0].Filename, p.Files()[0].Checksums.MD5)
|
||||||
|
|
||||||
list, err := p.DownloadList(packagePool, cs)
|
list, err := p.DownloadList(packagePool)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(list, DeepEquals, []PackageDownloadTask{
|
c.Check(list, DeepEquals, []PackageDownloadTask{
|
||||||
{
|
{
|
||||||
File: &p.Files()[0],
|
RepoURI: "pool/contrib/a/alien-arena/alien-arena-common_7.40-2_i386.deb",
|
||||||
},
|
DestinationPath: poolPath,
|
||||||
})
|
Checksums: utils.ChecksumInfo{Size: 5,
|
||||||
|
MD5: "1e8cba92c41420aa7baa8a5718d67122",
|
||||||
|
SHA1: "46955e48cad27410a83740a21d766ce362364024",
|
||||||
|
SHA256: "eb4afb9885cba6dc70cccd05b910b2dbccc02c5900578be5e99f0d3dbf9d76a5"}}})
|
||||||
|
|
||||||
tmpFilepath := filepath.Join(c.MkDir(), "file")
|
err = os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
c.Assert(ioutil.WriteFile(tmpFilepath, []byte("abcde"), 0777), IsNil)
|
c.Assert(err, IsNil)
|
||||||
p.Files()[0].PoolPath, _ = packagePool.Import(tmpFilepath, p.Files()[0].Filename, &p.Files()[0].Checksums, false, cs)
|
|
||||||
|
|
||||||
list, err = p.DownloadList(packagePool, cs)
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.WriteString("abcde")
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
list, err = p.DownloadList(packagePool)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(list, DeepEquals, []PackageDownloadTask{})
|
c.Check(list, DeepEquals, []PackageDownloadTask{})
|
||||||
}
|
}
|
||||||
@@ -418,22 +428,24 @@ func (s *PackageSuite) TestDownloadList(c *C) {
|
|||||||
func (s *PackageSuite) TestVerifyFiles(c *C) {
|
func (s *PackageSuite) TestVerifyFiles(c *C) {
|
||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
packagePool := files.NewPackagePool(c.MkDir(), false)
|
packagePool := files.NewPackagePool(c.MkDir())
|
||||||
cs := files.NewMockChecksumStorage()
|
poolPath, _ := packagePool.Path(p.Files()[0].Filename, p.Files()[0].Checksums.MD5)
|
||||||
|
|
||||||
tmpFilepath := filepath.Join(c.MkDir(), "file")
|
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
c.Assert(ioutil.WriteFile(tmpFilepath, []byte("abcde"), 0777), IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
p.Files()[0].PoolPath, _ = packagePool.Import(tmpFilepath, p.Files()[0].Filename, &p.Files()[0].Checksums, false, cs)
|
file, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
file.WriteString("abcde")
|
||||||
|
file.Close()
|
||||||
|
|
||||||
p.Files()[0].Checksums.Size = 100
|
result, err := p.VerifyFiles(packagePool)
|
||||||
result, err := p.VerifyFiles(packagePool, cs)
|
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(result, Equals, false)
|
c.Check(result, Equals, false)
|
||||||
|
|
||||||
p.Files()[0].Checksums.Size = 5
|
p.Files()[0].Checksums.Size = 5
|
||||||
|
|
||||||
result, err = p.VerifyFiles(packagePool, cs)
|
result, err = p.VerifyFiles(packagePool)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
c.Check(result, Equals, true)
|
c.Check(result, Equals, true)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ppaRegexp = regexp.MustCompile("^ppa:([^/]+)/(.+)$")
|
var ppaRegexp = regexp.MustCompile("^ppa:([^/]+)/(.+)$")
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package deb
|
package deb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aptly-dev/aptly/utils"
|
"github.com/smira/aptly/utils"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|||||||
+60
-131
@@ -17,10 +17,9 @@ import (
|
|||||||
"github.com/smira/go-uuid/uuid"
|
"github.com/smira/go-uuid/uuid"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/aptly-dev/aptly/pgp"
|
"github.com/smira/aptly/utils"
|
||||||
"github.com/aptly-dev/aptly/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type repoSourceItem struct {
|
type repoSourceItem struct {
|
||||||
@@ -41,13 +40,13 @@ type PublishedRepo struct {
|
|||||||
Prefix string
|
Prefix string
|
||||||
Distribution string
|
Distribution string
|
||||||
Origin string
|
Origin string
|
||||||
NotAutomatic string
|
|
||||||
ButAutomaticUpgrades string
|
|
||||||
Label string
|
Label string
|
||||||
// Architectures is a list of all architectures published
|
// Architectures is a list of all architectures published
|
||||||
Architectures []string
|
Architectures []string
|
||||||
// SourceKind is "local"/"repo"
|
// SourceKind is "local"/"repo"
|
||||||
SourceKind string
|
SourceKind string
|
||||||
|
// Skip contents generation
|
||||||
|
SkipContents bool
|
||||||
|
|
||||||
// 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
|
||||||
@@ -56,17 +55,12 @@ type PublishedRepo struct {
|
|||||||
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"`
|
||||||
|
|
||||||
// Map of component to source items
|
// Map of component to source items
|
||||||
sourceItems map[string]repoSourceItem
|
sourceItems map[string]repoSourceItem
|
||||||
|
|
||||||
// Skip contents generation
|
|
||||||
SkipContents bool
|
|
||||||
|
|
||||||
// True if repo is being re-published
|
// True if repo is being re-published
|
||||||
rePublishing bool
|
rePublishing bool
|
||||||
|
|
||||||
// Provide index files per hash also
|
|
||||||
AcquireByHash bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParsePrefix splits [storage:]prefix into components
|
// ParsePrefix splits [storage:]prefix into components
|
||||||
@@ -81,7 +75,6 @@ func ParsePrefix(param string) (storage, prefix string) {
|
|||||||
} else {
|
} else {
|
||||||
prefix = param
|
prefix = param
|
||||||
}
|
}
|
||||||
prefix = strings.TrimPrefix(strings.TrimSuffix(prefix, "/"), "/")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,19 +96,19 @@ func walkUpTree(source interface{}, collectionFactory *CollectionFactory) (rootD
|
|||||||
|
|
||||||
if snapshot, ok := head.(*Snapshot); ok {
|
if snapshot, ok := head.(*Snapshot); ok {
|
||||||
for _, uuid := range snapshot.SourceIDs {
|
for _, uuid := range snapshot.SourceIDs {
|
||||||
if snapshot.SourceKind == SourceRemoteRepo {
|
if snapshot.SourceKind == "repo" {
|
||||||
remoteRepo, err := collectionFactory.RemoteRepoCollection().ByUUID(uuid)
|
remoteRepo, err := collectionFactory.RemoteRepoCollection().ByUUID(uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
current = append(current, remoteRepo)
|
current = append(current, remoteRepo)
|
||||||
} else if snapshot.SourceKind == SourceLocalRepo {
|
} else if snapshot.SourceKind == "local" {
|
||||||
localRepo, err := collectionFactory.LocalRepoCollection().ByUUID(uuid)
|
localRepo, err := collectionFactory.LocalRepoCollection().ByUUID(uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
current = append(current, localRepo)
|
current = append(current, localRepo)
|
||||||
} else if snapshot.SourceKind == SourceSnapshot {
|
} else if snapshot.SourceKind == "snapshot" {
|
||||||
snap, err := collectionFactory.SnapshotCollection().ByUUID(uuid)
|
snap, err := collectionFactory.SnapshotCollection().ByUUID(uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -173,21 +166,24 @@ func NewPublishedRepo(storage, prefix, distribution string, architectures []stri
|
|||||||
component string
|
component string
|
||||||
snapshot *Snapshot
|
snapshot *Snapshot
|
||||||
localRepo *LocalRepo
|
localRepo *LocalRepo
|
||||||
fields = make(map[string][]string)
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// get first source
|
// get first source
|
||||||
source = sources[0]
|
source = sources[0]
|
||||||
|
|
||||||
// figure out source kind
|
// figure out source kind
|
||||||
switch source.(type) {
|
snapshot, ok = source.(*Snapshot)
|
||||||
case *Snapshot:
|
if ok {
|
||||||
result.SourceKind = SourceSnapshot
|
result.SourceKind = "snapshot"
|
||||||
case *LocalRepo:
|
} else {
|
||||||
result.SourceKind = SourceLocalRepo
|
localRepo, ok = source.(*LocalRepo)
|
||||||
default:
|
if ok {
|
||||||
|
result.SourceKind = "local"
|
||||||
|
} else {
|
||||||
panic("unknown source kind")
|
panic("unknown source kind")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i := range sources {
|
for i := range sources {
|
||||||
component, source = components[i], sources[i]
|
component, source = components[i], sources[i]
|
||||||
@@ -217,21 +213,11 @@ func NewPublishedRepo(storage, prefix, distribution string, architectures []stri
|
|||||||
return nil, fmt.Errorf("duplicate component name: %s", component)
|
return nil, fmt.Errorf("duplicate component name: %s", component)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.SourceKind == SourceSnapshot {
|
if result.SourceKind == "snapshot" {
|
||||||
snapshot = source.(*Snapshot)
|
snapshot = source.(*Snapshot)
|
||||||
result.Sources[component] = snapshot.UUID
|
result.Sources[component] = snapshot.UUID
|
||||||
result.sourceItems[component] = repoSourceItem{snapshot: snapshot}
|
result.sourceItems[component] = repoSourceItem{snapshot: snapshot}
|
||||||
|
} else if result.SourceKind == "local" {
|
||||||
if !utils.StrSliceHasItem(fields["Origin"], snapshot.Origin) {
|
|
||||||
fields["Origin"] = append(fields["Origin"], snapshot.Origin)
|
|
||||||
}
|
|
||||||
if !utils.StrSliceHasItem(fields["NotAutomatic"], snapshot.NotAutomatic) {
|
|
||||||
fields["NotAutomatic"] = append(fields["NotAutomatic"], snapshot.NotAutomatic)
|
|
||||||
}
|
|
||||||
if !utils.StrSliceHasItem(fields["ButAutomaticUpgrades"], snapshot.ButAutomaticUpgrades) {
|
|
||||||
fields["ButAutomaticUpgrades"] = append(fields["ButAutomaticUpgrades"], snapshot.ButAutomaticUpgrades)
|
|
||||||
}
|
|
||||||
} else if result.SourceKind == SourceLocalRepo {
|
|
||||||
localRepo = source.(*LocalRepo)
|
localRepo = source.(*LocalRepo)
|
||||||
result.Sources[component] = localRepo.UUID
|
result.Sources[component] = localRepo.UUID
|
||||||
result.sourceItems[component] = repoSourceItem{localRepo: localRepo, packageRefs: localRepo.RefList()}
|
result.sourceItems[component] = repoSourceItem{localRepo: localRepo, packageRefs: localRepo.RefList()}
|
||||||
@@ -240,7 +226,12 @@ func NewPublishedRepo(storage, prefix, distribution string, architectures []stri
|
|||||||
|
|
||||||
// clean & verify prefix
|
// clean & verify prefix
|
||||||
prefix = filepath.Clean(prefix)
|
prefix = filepath.Clean(prefix)
|
||||||
prefix = strings.TrimPrefix(strings.TrimSuffix(prefix, "/"), "/")
|
if strings.HasPrefix(prefix, "/") {
|
||||||
|
prefix = prefix[1:]
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(prefix, "/") {
|
||||||
|
prefix = prefix[:len(prefix)-1]
|
||||||
|
}
|
||||||
prefix = filepath.Clean(prefix)
|
prefix = filepath.Clean(prefix)
|
||||||
|
|
||||||
for _, part := range strings.Split(prefix, "/") {
|
for _, part := range strings.Split(prefix, "/") {
|
||||||
@@ -261,23 +252,12 @@ func NewPublishedRepo(storage, prefix, distribution string, architectures []stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(distribution, "/") {
|
if strings.Index(distribution, "/") != -1 {
|
||||||
return nil, fmt.Errorf("invalid distribution %s, '/' is not allowed", distribution)
|
return nil, fmt.Errorf("invalid distribution %s, '/' is not allowed", distribution)
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Distribution = distribution
|
result.Distribution = distribution
|
||||||
|
|
||||||
// only fields which are unique by all given snapshots are set on published
|
|
||||||
if len(fields["Origin"]) == 1 {
|
|
||||||
result.Origin = fields["Origin"][0]
|
|
||||||
}
|
|
||||||
if len(fields["NotAutomatic"]) == 1 {
|
|
||||||
result.NotAutomatic = fields["NotAutomatic"][0]
|
|
||||||
}
|
|
||||||
if len(fields["ButAutomaticUpgrades"]) == 1 {
|
|
||||||
result.ButAutomaticUpgrades = fields["ButAutomaticUpgrades"][0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,14 +288,11 @@ func (p *PublishedRepo) MarshalJSON() ([]byte, error) {
|
|||||||
"Distribution": p.Distribution,
|
"Distribution": p.Distribution,
|
||||||
"Label": p.Label,
|
"Label": p.Label,
|
||||||
"Origin": p.Origin,
|
"Origin": p.Origin,
|
||||||
"NotAutomatic": p.NotAutomatic,
|
|
||||||
"ButAutomaticUpgrades": p.ButAutomaticUpgrades,
|
|
||||||
"Prefix": p.Prefix,
|
"Prefix": p.Prefix,
|
||||||
"SourceKind": p.SourceKind,
|
"SourceKind": p.SourceKind,
|
||||||
"Sources": sources,
|
"Sources": sources,
|
||||||
"Storage": p.Storage,
|
"Storage": p.Storage,
|
||||||
"SkipContents": p.SkipContents,
|
"SkipContents": p.SkipContents,
|
||||||
"AcquireByHash": p.AcquireByHash,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,26 +315,18 @@ func (p *PublishedRepo) String() string {
|
|||||||
sources = append(sources, fmt.Sprintf("{%s: %s}", component, source))
|
sources = append(sources, fmt.Sprintf("{%s: %s}", component, source))
|
||||||
}
|
}
|
||||||
|
|
||||||
var extras []string
|
|
||||||
var extra string
|
var extra string
|
||||||
|
|
||||||
if p.Origin != "" {
|
if p.Origin != "" {
|
||||||
extras = append(extras, fmt.Sprintf("origin: %s", p.Origin))
|
extra += fmt.Sprintf("origin: %s", p.Origin)
|
||||||
}
|
|
||||||
|
|
||||||
if p.NotAutomatic != "" {
|
|
||||||
extras = append(extras, fmt.Sprintf("notautomatic: %s", p.NotAutomatic))
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.ButAutomaticUpgrades != "" {
|
|
||||||
extras = append(extras, fmt.Sprintf("butautomaticupgrades: %s", p.ButAutomaticUpgrades))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Label != "" {
|
if p.Label != "" {
|
||||||
extras = append(extras, fmt.Sprintf("label: %s", p.Label))
|
if extra != "" {
|
||||||
|
extra += ", "
|
||||||
|
}
|
||||||
|
extra += fmt.Sprintf("label: %s", p.Label)
|
||||||
}
|
}
|
||||||
|
|
||||||
extra = strings.Join(extras, ", ")
|
|
||||||
|
|
||||||
if extra != "" {
|
if extra != "" {
|
||||||
extra = " (" + extra + ")"
|
extra = " (" + extra + ")"
|
||||||
@@ -389,10 +358,10 @@ func (p *PublishedRepo) RefKey(component string) []byte {
|
|||||||
// RefList returns list of package refs in local repo
|
// RefList returns list of package refs in local repo
|
||||||
func (p *PublishedRepo) RefList(component string) *PackageRefList {
|
func (p *PublishedRepo) RefList(component string) *PackageRefList {
|
||||||
item := p.sourceItems[component]
|
item := p.sourceItems[component]
|
||||||
if p.SourceKind == SourceLocalRepo {
|
if p.SourceKind == "local" {
|
||||||
return item.packageRefs
|
return item.packageRefs
|
||||||
}
|
}
|
||||||
if p.SourceKind == SourceSnapshot {
|
if p.SourceKind == "snapshot" {
|
||||||
return item.snapshot.RefList()
|
return item.snapshot.RefList()
|
||||||
}
|
}
|
||||||
panic("unknown source")
|
panic("unknown source")
|
||||||
@@ -411,7 +380,7 @@ func (p *PublishedRepo) Components() []string {
|
|||||||
|
|
||||||
// UpdateLocalRepo updates content from local repo in component
|
// UpdateLocalRepo updates content from local repo in component
|
||||||
func (p *PublishedRepo) UpdateLocalRepo(component string) {
|
func (p *PublishedRepo) UpdateLocalRepo(component string) {
|
||||||
if p.SourceKind != SourceLocalRepo {
|
if p.SourceKind != "local" {
|
||||||
panic("not local repo publish")
|
panic("not local repo publish")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +393,7 @@ func (p *PublishedRepo) UpdateLocalRepo(component string) {
|
|||||||
|
|
||||||
// UpdateSnapshot switches snapshot for component
|
// UpdateSnapshot switches snapshot for component
|
||||||
func (p *PublishedRepo) UpdateSnapshot(component string, snapshot *Snapshot) {
|
func (p *PublishedRepo) UpdateSnapshot(component string, snapshot *Snapshot) {
|
||||||
if p.SourceKind != SourceSnapshot {
|
if p.SourceKind != "snapshot" {
|
||||||
panic("not snapshot publish")
|
panic("not snapshot publish")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +425,7 @@ func (p *PublishedRepo) Decode(input []byte) error {
|
|||||||
|
|
||||||
// old PublishedRepo were publishing only snapshots
|
// old PublishedRepo were publishing only snapshots
|
||||||
if p.SourceKind == "" {
|
if p.SourceKind == "" {
|
||||||
p.SourceKind = SourceSnapshot
|
p.SourceKind = "snapshot"
|
||||||
}
|
}
|
||||||
|
|
||||||
// <0.6 aptly used single SourceUUID + Component instead of Sources
|
// <0.6 aptly used single SourceUUID + Component instead of Sources
|
||||||
@@ -487,7 +456,7 @@ func (p *PublishedRepo) GetLabel() string {
|
|||||||
|
|
||||||
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
||||||
func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageProvider aptly.PublishedStorageProvider,
|
func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageProvider aptly.PublishedStorageProvider,
|
||||||
collectionFactory *CollectionFactory, signer pgp.Signer, progress aptly.Progress, forceOverwrite bool) error {
|
collectionFactory *CollectionFactory, signer utils.Signer, progress aptly.Progress, forceOverwrite bool) error {
|
||||||
publishedStorage := publishedStorageProvider.GetPublishedStorage(p.Storage)
|
publishedStorage := publishedStorageProvider.GetPublishedStorage(p.Storage)
|
||||||
|
|
||||||
err := publishedStorage.MkDir(filepath.Join(p.Prefix, "pool"))
|
err := publishedStorage.MkDir(filepath.Join(p.Prefix, "pool"))
|
||||||
@@ -505,7 +474,8 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
e := tempDB.Close()
|
var e error
|
||||||
|
e = tempDB.Close()
|
||||||
if e != nil && progress != nil {
|
if e != nil && progress != nil {
|
||||||
progress.Printf("failed to close temp DB: %s", err)
|
progress.Printf("failed to close temp DB: %s", err)
|
||||||
}
|
}
|
||||||
@@ -560,9 +530,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
}
|
}
|
||||||
defer os.RemoveAll(tempDir)
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
indexes := newIndexFiles(publishedStorage, basePath, tempDir, suffix, p.AcquireByHash)
|
indexes := newIndexFiles(publishedStorage, basePath, tempDir, suffix)
|
||||||
|
|
||||||
legacyContentIndexes := map[string]*ContentsIndex{}
|
|
||||||
|
|
||||||
for component, list := range lists {
|
for component, list := range lists {
|
||||||
hadUdebs := false
|
hadUdebs := false
|
||||||
@@ -601,32 +569,21 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a db batch. If we fill contents data we'll need
|
|
||||||
// to push each path of the package into the database.
|
|
||||||
// We'll want this batched so as to avoid an excessive
|
|
||||||
// amount of write() calls.
|
|
||||||
tempDB.StartBatch()
|
|
||||||
defer tempDB.FinishBatch()
|
|
||||||
|
|
||||||
for _, arch := range p.Architectures {
|
for _, arch := range p.Architectures {
|
||||||
if pkg.MatchesArchitecture(arch) {
|
if pkg.MatchesArchitecture(arch) {
|
||||||
var bufWriter *bufio.Writer
|
var bufWriter *bufio.Writer
|
||||||
|
|
||||||
if !p.SkipContents {
|
if !p.SkipContents {
|
||||||
key := fmt.Sprintf("%s-%v", arch, pkg.IsUdeb)
|
key := fmt.Sprintf("%s-%v", arch, pkg.IsUdeb)
|
||||||
qualifiedName := []byte(pkg.QualifiedName())
|
|
||||||
contents := pkg.Contents(packagePool, progress)
|
|
||||||
|
|
||||||
for _, contentIndexesMap := range []map[string]*ContentsIndex{contentIndexes, legacyContentIndexes} {
|
contentIndex := contentIndexes[key]
|
||||||
contentIndex := contentIndexesMap[key]
|
|
||||||
|
|
||||||
if contentIndex == nil {
|
if contentIndex == nil {
|
||||||
contentIndex = NewContentsIndex(tempDB)
|
contentIndex = NewContentsIndex(tempDB)
|
||||||
contentIndexesMap[key] = contentIndex
|
contentIndexes[key] = contentIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
contentIndex.Push(qualifiedName, contents)
|
contentIndex.Push(pkg, packagePool)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bufWriter, err = indexes.PackageIndex(component, arch, pkg.IsUdeb).BufWriter()
|
bufWriter, err = indexes.PackageIndex(component, arch, pkg.IsUdeb).BufWriter()
|
||||||
@@ -664,8 +621,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var bufWriter *bufio.Writer
|
bufWriter, err := indexes.ContentsIndex(component, arch, udeb).BufWriter()
|
||||||
bufWriter, err = indexes.ContentsIndex(component, arch, udeb).BufWriter()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to generate contents index: %v", err)
|
return fmt.Errorf("unable to generate contents index: %v", err)
|
||||||
}
|
}
|
||||||
@@ -700,9 +656,6 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
release["Component"] = component
|
release["Component"] = component
|
||||||
release["Origin"] = p.GetOrigin()
|
release["Origin"] = p.GetOrigin()
|
||||||
release["Label"] = p.GetLabel()
|
release["Label"] = p.GetLabel()
|
||||||
if p.AcquireByHash {
|
|
||||||
release["Acquire-By-Hash"] = "yes"
|
|
||||||
}
|
|
||||||
|
|
||||||
var bufWriter *bufio.Writer
|
var bufWriter *bufio.Writer
|
||||||
bufWriter, err = indexes.ReleaseIndex(component, arch, udeb).BufWriter()
|
bufWriter, err = indexes.ReleaseIndex(component, arch, udeb).BufWriter()
|
||||||
@@ -718,26 +671,6 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, arch := range p.Architectures {
|
|
||||||
for _, udeb := range []bool{true, false} {
|
|
||||||
index := legacyContentIndexes[fmt.Sprintf("%s-%v", arch, udeb)]
|
|
||||||
if index == nil || index.Empty() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var bufWriter *bufio.Writer
|
|
||||||
bufWriter, err = indexes.LegacyContentsIndex(arch, udeb).BufWriter()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to generate contents index: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = index.WriteTo(bufWriter)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to generate contents index: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if progress != nil {
|
if progress != nil {
|
||||||
progress.Printf("Finalizing metadata files...\n")
|
progress.Printf("Finalizing metadata files...\n")
|
||||||
}
|
}
|
||||||
@@ -749,20 +682,11 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
|
|
||||||
release := make(Stanza)
|
release := make(Stanza)
|
||||||
release["Origin"] = p.GetOrigin()
|
release["Origin"] = p.GetOrigin()
|
||||||
if p.NotAutomatic != "" {
|
|
||||||
release["NotAutomatic"] = p.NotAutomatic
|
|
||||||
}
|
|
||||||
if p.ButAutomaticUpgrades != "" {
|
|
||||||
release["ButAutomaticUpgrades"] = p.ButAutomaticUpgrades
|
|
||||||
}
|
|
||||||
release["Label"] = p.GetLabel()
|
release["Label"] = p.GetLabel()
|
||||||
release["Suite"] = p.Distribution
|
release["Suite"] = p.Distribution
|
||||||
release["Codename"] = p.Distribution
|
release["Codename"] = p.Distribution
|
||||||
release["Date"] = time.Now().UTC().Format("Mon, 2 Jan 2006 15:04:05 MST")
|
release["Date"] = time.Now().UTC().Format("Mon, 2 Jan 2006 15:04:05 MST")
|
||||||
release["Architectures"] = strings.Join(utils.StrSlicesSubstract(p.Architectures, []string{ArchitectureSource}), " ")
|
release["Architectures"] = strings.Join(utils.StrSlicesSubstract(p.Architectures, []string{"source"}), " ")
|
||||||
if p.AcquireByHash {
|
|
||||||
release["Acquire-By-Hash"] = "yes"
|
|
||||||
}
|
|
||||||
release["Description"] = " Generated by aptly\n"
|
release["Description"] = " Generated by aptly\n"
|
||||||
release["MD5Sum"] = ""
|
release["MD5Sum"] = ""
|
||||||
release["SHA1"] = ""
|
release["SHA1"] = ""
|
||||||
@@ -806,7 +730,12 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexes.RenameFiles()
|
err = indexes.RenameFiles()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFiles removes files that were created by Publish
|
// RemoveFiles removes files that were created by Publish
|
||||||
@@ -905,7 +834,7 @@ func (collection *PublishedRepoCollection) Update(repo *PublishedRepo) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.SourceKind == SourceLocalRepo {
|
if repo.SourceKind == "local" {
|
||||||
for component, item := range repo.sourceItems {
|
for component, item := range repo.sourceItems {
|
||||||
err = collection.db.Put(repo.RefKey(component), item.packageRefs.Encode())
|
err = collection.db.Put(repo.RefKey(component), item.packageRefs.Encode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -920,7 +849,7 @@ func (collection *PublishedRepoCollection) Update(repo *PublishedRepo) (err erro
|
|||||||
func (collection *PublishedRepoCollection) LoadComplete(repo *PublishedRepo, collectionFactory *CollectionFactory) (err error) {
|
func (collection *PublishedRepoCollection) LoadComplete(repo *PublishedRepo, collectionFactory *CollectionFactory) (err error) {
|
||||||
repo.sourceItems = make(map[string]repoSourceItem)
|
repo.sourceItems = make(map[string]repoSourceItem)
|
||||||
|
|
||||||
if repo.SourceKind == SourceSnapshot {
|
if repo.SourceKind == "snapshot" {
|
||||||
for component, sourceUUID := range repo.Sources {
|
for component, sourceUUID := range repo.Sources {
|
||||||
item := repoSourceItem{}
|
item := repoSourceItem{}
|
||||||
|
|
||||||
@@ -935,7 +864,7 @@ func (collection *PublishedRepoCollection) LoadComplete(repo *PublishedRepo, col
|
|||||||
|
|
||||||
repo.sourceItems[component] = item
|
repo.sourceItems[component] = item
|
||||||
}
|
}
|
||||||
} else if repo.SourceKind == SourceLocalRepo {
|
} else if repo.SourceKind == "local" {
|
||||||
for component, sourceUUID := range repo.Sources {
|
for component, sourceUUID := range repo.Sources {
|
||||||
item := repoSourceItem{}
|
item := repoSourceItem{}
|
||||||
|
|
||||||
@@ -1003,7 +932,7 @@ func (collection *PublishedRepoCollection) ByUUID(uuid string) (*PublishedRepo,
|
|||||||
func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*PublishedRepo {
|
func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*PublishedRepo {
|
||||||
var result []*PublishedRepo
|
var result []*PublishedRepo
|
||||||
for _, r := range collection.list {
|
for _, r := range collection.list {
|
||||||
if r.SourceKind == SourceSnapshot {
|
if r.SourceKind == "snapshot" {
|
||||||
if r.SourceUUID == snapshot.UUID {
|
if r.SourceUUID == snapshot.UUID {
|
||||||
result = append(result, r)
|
result = append(result, r)
|
||||||
}
|
}
|
||||||
@@ -1023,7 +952,7 @@ func (collection *PublishedRepoCollection) BySnapshot(snapshot *Snapshot) []*Pub
|
|||||||
func (collection *PublishedRepoCollection) ByLocalRepo(repo *LocalRepo) []*PublishedRepo {
|
func (collection *PublishedRepoCollection) ByLocalRepo(repo *LocalRepo) []*PublishedRepo {
|
||||||
var result []*PublishedRepo
|
var result []*PublishedRepo
|
||||||
for _, r := range collection.list {
|
for _, r := range collection.list {
|
||||||
if r.SourceKind == SourceLocalRepo {
|
if r.SourceKind == "local" {
|
||||||
if r.SourceUUID == repo.UUID {
|
if r.SourceUUID == repo.UUID {
|
||||||
result = append(result, r)
|
result = append(result, r)
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1069,7 @@ func (collection *PublishedRepoCollection) CleanupPrefixComponentFiles(prefix st
|
|||||||
// Remove removes published repository, cleaning up directories, files
|
// Remove removes published repository, cleaning up directories, files
|
||||||
func (collection *PublishedRepoCollection) Remove(publishedStorageProvider aptly.PublishedStorageProvider,
|
func (collection *PublishedRepoCollection) Remove(publishedStorageProvider aptly.PublishedStorageProvider,
|
||||||
storage, prefix, distribution string, collectionFactory *CollectionFactory, progress aptly.Progress,
|
storage, prefix, distribution string, collectionFactory *CollectionFactory, progress aptly.Progress,
|
||||||
force, skipCleanup bool) error {
|
force bool) error {
|
||||||
repo, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
repo, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1177,7 +1106,7 @@ func (collection *PublishedRepoCollection) Remove(publishedStorageProvider aptly
|
|||||||
collection.list[len(collection.list)-1], collection.list[repoPosition], collection.list =
|
collection.list[len(collection.list)-1], collection.list[repoPosition], collection.list =
|
||||||
nil, collection.list[len(collection.list)-1], collection.list[:len(collection.list)-1]
|
nil, collection.list[len(collection.list)-1], collection.list[:len(collection.list)-1]
|
||||||
|
|
||||||
if !skipCleanup && len(cleanComponents) > 0 {
|
if len(cleanComponents) > 0 {
|
||||||
err = collection.CleanupPrefixComponentFiles(repo.Prefix, cleanComponents,
|
err = collection.CleanupPrefixComponentFiles(repo.Prefix, cleanComponents,
|
||||||
publishedStorageProvider.GetPublishedStorage(storage), collectionFactory, progress)
|
publishedStorageProvider.GetPublishedStorage(storage), collectionFactory, progress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+29
-77
@@ -8,9 +8,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/aptly-dev/aptly/aptly"
|
"github.com/smira/aptly/aptly"
|
||||||
"github.com/aptly-dev/aptly/database"
|
"github.com/smira/aptly/database"
|
||||||
"github.com/aptly-dev/aptly/files"
|
"github.com/smira/aptly/files"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
@@ -74,7 +74,6 @@ type PublishedRepoSuite struct {
|
|||||||
provider *FakeStorageProvider
|
provider *FakeStorageProvider
|
||||||
publishedStorage, publishedStorage2 *files.PublishedStorage
|
publishedStorage, publishedStorage2 *files.PublishedStorage
|
||||||
packagePool aptly.PackagePool
|
packagePool aptly.PackagePool
|
||||||
cs aptly.ChecksumStorage
|
|
||||||
localRepo *LocalRepo
|
localRepo *LocalRepo
|
||||||
snapshot, snapshot2 *Snapshot
|
snapshot, snapshot2 *Snapshot
|
||||||
db database.Storage
|
db database.Storage
|
||||||
@@ -87,31 +86,17 @@ var _ = Suite(&PublishedRepoSuite{})
|
|||||||
func (s *PublishedRepoSuite) SetUpTest(c *C) {
|
func (s *PublishedRepoSuite) SetUpTest(c *C) {
|
||||||
s.SetUpPackages()
|
s.SetUpPackages()
|
||||||
|
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.factory = NewCollectionFactory(s.db)
|
s.factory = NewCollectionFactory(s.db)
|
||||||
|
|
||||||
s.root = c.MkDir()
|
s.root = c.MkDir()
|
||||||
s.publishedStorage = files.NewPublishedStorage(s.root, "", "")
|
s.publishedStorage = files.NewPublishedStorage(s.root)
|
||||||
s.root2 = c.MkDir()
|
s.root2 = c.MkDir()
|
||||||
s.publishedStorage2 = files.NewPublishedStorage(s.root2, "", "")
|
s.publishedStorage2 = files.NewPublishedStorage(s.root2)
|
||||||
s.provider = &FakeStorageProvider{map[string]aptly.PublishedStorage{
|
s.provider = &FakeStorageProvider{map[string]aptly.PublishedStorage{
|
||||||
"": s.publishedStorage,
|
"": s.publishedStorage,
|
||||||
"files:other": s.publishedStorage2}}
|
"files:other": s.publishedStorage2}}
|
||||||
s.packagePool = files.NewPackagePool(s.root, false)
|
s.packagePool = files.NewPackagePool(s.root)
|
||||||
s.cs = files.NewMockChecksumStorage()
|
|
||||||
|
|
||||||
tmpFilepath := filepath.Join(c.MkDir(), "file")
|
|
||||||
c.Assert(ioutil.WriteFile(tmpFilepath, nil, 0777), IsNil)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
s.p1.Files()[0].PoolPath, err = s.packagePool.Import(tmpFilepath, s.p1.Files()[0].Filename, &s.p1.Files()[0].Checksums, false, s.cs)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
s.p1.UpdateFiles(s.p1.Files())
|
|
||||||
s.p2.UpdateFiles(s.p1.Files())
|
|
||||||
s.p3.UpdateFiles(s.p1.Files())
|
|
||||||
|
|
||||||
s.reflist = NewPackageRefListFromPackageList(s.list)
|
|
||||||
|
|
||||||
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{}, false, false)
|
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{}, false, false)
|
||||||
repo.packageRefs = s.reflist
|
repo.packageRefs = s.reflist
|
||||||
@@ -146,6 +131,12 @@ func (s *PublishedRepoSuite) SetUpTest(c *C) {
|
|||||||
|
|
||||||
s.repo5, _ = NewPublishedRepo("files:other", "ppa", "maverick", []string{"source"}, []string{"main"}, []interface{}{s.localRepo}, s.factory)
|
s.repo5, _ = NewPublishedRepo("files:other", "ppa", "maverick", []string{"source"}, []string{"main"}, []interface{}{s.localRepo}, s.factory)
|
||||||
s.repo5.SkipContents = true
|
s.repo5.SkipContents = true
|
||||||
|
|
||||||
|
poolPath, _ := s.packagePool.Path(s.p1.Files()[0].Filename, s.p1.Files()[0].Checksums.MD5)
|
||||||
|
err := os.MkdirAll(filepath.Dir(poolPath), 0755)
|
||||||
|
f, err := os.Create(poolPath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoSuite) TearDownTest(c *C) {
|
func (s *PublishedRepoSuite) TearDownTest(c *C) {
|
||||||
@@ -277,7 +268,7 @@ func (s *PublishedRepoSuite) TestDistributionComponentGuessing(c *C) {
|
|||||||
c.Check(repo.Distribution, Equals, "squeeze")
|
c.Check(repo.Distribution, Equals, "squeeze")
|
||||||
c.Check(repo.Components(), DeepEquals, []string{"main"})
|
c.Check(repo.Components(), DeepEquals, []string{"main"})
|
||||||
|
|
||||||
_, err = NewPublishedRepo("", "ppa", "", nil, []string{"main"}, []interface{}{s.localRepo}, s.factory)
|
repo, err = NewPublishedRepo("", "ppa", "", nil, []string{"main"}, []interface{}{s.localRepo}, s.factory)
|
||||||
c.Check(err, ErrorMatches, "unable to guess distribution name, please specify explicitly")
|
c.Check(err, ErrorMatches, "unable to guess distribution name, please specify explicitly")
|
||||||
|
|
||||||
s.localRepo.DefaultDistribution = "precise"
|
s.localRepo.DefaultDistribution = "precise"
|
||||||
@@ -301,7 +292,7 @@ func (s *PublishedRepoSuite) TestDistributionComponentGuessing(c *C) {
|
|||||||
c.Check(repo.Distribution, Equals, "squeeze")
|
c.Check(repo.Distribution, Equals, "squeeze")
|
||||||
c.Check(repo.Components(), DeepEquals, []string{"contrib", "main"})
|
c.Check(repo.Components(), DeepEquals, []string{"contrib", "main"})
|
||||||
|
|
||||||
_, err = NewPublishedRepo("", "ppa", "", nil, []string{"", ""}, []interface{}{s.snapshot, s.snapshot2}, s.factory)
|
repo, err = NewPublishedRepo("", "ppa", "", nil, []string{"", ""}, []interface{}{s.snapshot, s.snapshot2}, s.factory)
|
||||||
c.Check(err, ErrorMatches, "duplicate component name: main")
|
c.Check(err, ErrorMatches, "duplicate component name: main")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +440,7 @@ type PublishedRepoCollectionSuite struct {
|
|||||||
var _ = Suite(&PublishedRepoCollectionSuite{})
|
var _ = Suite(&PublishedRepoCollectionSuite{})
|
||||||
|
|
||||||
func (s *PublishedRepoCollectionSuite) SetUpTest(c *C) {
|
func (s *PublishedRepoCollectionSuite) SetUpTest(c *C) {
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.factory = NewCollectionFactory(s.db)
|
s.factory = NewCollectionFactory(s.db)
|
||||||
|
|
||||||
s.snapshotCollection = s.factory.SnapshotCollection()
|
s.snapshotCollection = s.factory.SnapshotCollection()
|
||||||
@@ -477,7 +468,7 @@ func (s *PublishedRepoCollectionSuite) TearDownTest(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoCollectionSuite) TestAddByStoragePrefixDistribution(c *C) {
|
func (s *PublishedRepoCollectionSuite) TestAddByStoragePrefixDistribution(c *C) {
|
||||||
_, err := s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
r, err := s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
||||||
c.Assert(err, ErrorMatches, "*.not found")
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
c.Assert(s.collection.Add(s.repo1), IsNil)
|
c.Assert(s.collection.Add(s.repo1), IsNil)
|
||||||
@@ -489,7 +480,7 @@ func (s *PublishedRepoCollectionSuite) TestAddByStoragePrefixDistribution(c *C)
|
|||||||
c.Assert(s.collection.Add(s.repo4), IsNil)
|
c.Assert(s.collection.Add(s.repo4), IsNil)
|
||||||
c.Assert(s.collection.Add(s.repo5), IsNil)
|
c.Assert(s.collection.Add(s.repo5), IsNil)
|
||||||
|
|
||||||
r, err := s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
r, err = s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.collection.LoadComplete(r, s.factory)
|
err = s.collection.LoadComplete(r, s.factory)
|
||||||
@@ -505,17 +496,16 @@ func (s *PublishedRepoCollectionSuite) TestAddByStoragePrefixDistribution(c *C)
|
|||||||
c.Assert(r.String(), Equals, s.repo1.String())
|
c.Assert(r.String(), Equals, s.repo1.String())
|
||||||
|
|
||||||
r, err = s.collection.ByStoragePrefixDistribution("files:other", "ppa", "precise")
|
r, err = s.collection.ByStoragePrefixDistribution("files:other", "ppa", "precise")
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Check(r.String(), Equals, s.repo5.String())
|
c.Check(r.String(), Equals, s.repo5.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoCollectionSuite) TestByUUID(c *C) {
|
func (s *PublishedRepoCollectionSuite) TestByUUID(c *C) {
|
||||||
_, err := s.collection.ByUUID(s.repo1.UUID)
|
r, err := s.collection.ByUUID(s.repo1.UUID)
|
||||||
c.Assert(err, ErrorMatches, "*.not found")
|
c.Assert(err, ErrorMatches, "*.not found")
|
||||||
|
|
||||||
c.Assert(s.collection.Add(s.repo1), IsNil)
|
c.Assert(s.collection.Add(s.repo1), IsNil)
|
||||||
|
|
||||||
r, err := s.collection.ByUUID(s.repo1.UUID)
|
r, err = s.collection.ByUUID(s.repo1.UUID)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.collection.LoadComplete(r, s.factory)
|
err = s.collection.LoadComplete(r, s.factory)
|
||||||
@@ -562,7 +552,7 @@ func (s *PublishedRepoCollectionSuite) TestLoadPre0_6(c *C) {
|
|||||||
Prefix: "ppa",
|
Prefix: "ppa",
|
||||||
Distribution: "anaconda",
|
Distribution: "anaconda",
|
||||||
Architectures: []string{"i386"},
|
Architectures: []string{"i386"},
|
||||||
SourceKind: SourceLocalRepo,
|
SourceKind: "local",
|
||||||
Component: "contrib",
|
Component: "contrib",
|
||||||
SourceUUID: s.localRepo.UUID,
|
SourceUUID: s.localRepo.UUID,
|
||||||
}
|
}
|
||||||
@@ -640,7 +630,7 @@ type PublishedRepoRemoveSuite struct {
|
|||||||
var _ = Suite(&PublishedRepoRemoveSuite{})
|
var _ = Suite(&PublishedRepoRemoveSuite{})
|
||||||
|
|
||||||
func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
|
func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
|
||||||
s.db, _ = database.NewOpenDB(c.MkDir())
|
s.db, _ = database.OpenDB(c.MkDir())
|
||||||
s.factory = NewCollectionFactory(s.db)
|
s.factory = NewCollectionFactory(s.db)
|
||||||
|
|
||||||
s.snapshotCollection = s.factory.SnapshotCollection()
|
s.snapshotCollection = s.factory.SnapshotCollection()
|
||||||
@@ -663,7 +653,7 @@ func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
|
|||||||
s.collection.Add(s.repo5)
|
s.collection.Add(s.repo5)
|
||||||
|
|
||||||
s.root = c.MkDir()
|
s.root = c.MkDir()
|
||||||
s.publishedStorage = files.NewPublishedStorage(s.root, "", "")
|
s.publishedStorage = files.NewPublishedStorage(s.root)
|
||||||
s.publishedStorage.MkDir("ppa/dists/anaconda")
|
s.publishedStorage.MkDir("ppa/dists/anaconda")
|
||||||
s.publishedStorage.MkDir("ppa/dists/meduza")
|
s.publishedStorage.MkDir("ppa/dists/meduza")
|
||||||
s.publishedStorage.MkDir("ppa/dists/osminog")
|
s.publishedStorage.MkDir("ppa/dists/osminog")
|
||||||
@@ -673,7 +663,7 @@ func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
|
|||||||
s.publishedStorage.MkDir("pool/main")
|
s.publishedStorage.MkDir("pool/main")
|
||||||
|
|
||||||
s.root2 = c.MkDir()
|
s.root2 = c.MkDir()
|
||||||
s.publishedStorage2 = files.NewPublishedStorage(s.root2, "", "")
|
s.publishedStorage2 = files.NewPublishedStorage(s.root2)
|
||||||
s.publishedStorage2.MkDir("ppa/dists/osminog")
|
s.publishedStorage2.MkDir("ppa/dists/osminog")
|
||||||
s.publishedStorage2.MkDir("ppa/pool/contrib")
|
s.publishedStorage2.MkDir("ppa/pool/contrib")
|
||||||
|
|
||||||
@@ -756,7 +746,7 @@ func (s *PublishedRepoRemoveSuite) TestRemoveFilesWithPrefixRoot(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2(c *C) {
|
func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2(c *C) {
|
||||||
err := s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false, false)
|
err := s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
_, err = s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
_, err = s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
||||||
@@ -776,48 +766,10 @@ func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2(c *C) {
|
|||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/dists/osminog"), PathExists)
|
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/dists/osminog"), PathExists)
|
||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/pool/contrib"), PathExists)
|
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/pool/contrib"), PathExists)
|
||||||
|
|
||||||
err = s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false, false)
|
err = s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false)
|
||||||
c.Check(err, ErrorMatches, ".*not found")
|
c.Check(err, ErrorMatches, ".*not found")
|
||||||
|
|
||||||
err = s.collection.Remove(s.provider, "", "ppa", "meduza", s.factory, nil, false, false)
|
err = s.collection.Remove(s.provider, "", "ppa", "meduza", s.factory, nil, false)
|
||||||
c.Check(err, IsNil)
|
|
||||||
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/meduza"), Not(PathExists))
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/osminog"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/pool/main"), Not(PathExists))
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/pool/contrib"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "dists/anaconda"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "pool/main"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/dists/osminog"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/pool/contrib"), PathExists)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2SkipCleanup(c *C) {
|
|
||||||
err := s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false, true)
|
|
||||||
c.Check(err, IsNil)
|
|
||||||
|
|
||||||
_, err = s.collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
|
||||||
c.Check(err, ErrorMatches, ".*not found")
|
|
||||||
|
|
||||||
collection := NewPublishedRepoCollection(s.db)
|
|
||||||
_, err = collection.ByStoragePrefixDistribution("", "ppa", "anaconda")
|
|
||||||
c.Check(err, ErrorMatches, ".*not found")
|
|
||||||
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/meduza"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/osminog"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/pool/main"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/pool/contrib"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "dists/anaconda"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "pool/main"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/dists/osminog"), PathExists)
|
|
||||||
c.Check(filepath.Join(s.publishedStorage2.PublicPath(), "ppa/pool/contrib"), PathExists)
|
|
||||||
|
|
||||||
err = s.collection.Remove(s.provider, "", "ppa", "anaconda", s.factory, nil, false, true)
|
|
||||||
c.Check(err, ErrorMatches, ".*not found")
|
|
||||||
|
|
||||||
err = s.collection.Remove(s.provider, "", "ppa", "meduza", s.factory, nil, false, true)
|
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
c.Check(filepath.Join(s.publishedStorage.PublicPath(), "ppa/dists/anaconda"), Not(PathExists))
|
||||||
@@ -832,7 +784,7 @@ func (s *PublishedRepoRemoveSuite) TestRemoveRepo1and2SkipCleanup(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoRemoveSuite) TestRemoveRepo3(c *C) {
|
func (s *PublishedRepoRemoveSuite) TestRemoveRepo3(c *C) {
|
||||||
err := s.collection.Remove(s.provider, "", ".", "anaconda", s.factory, nil, false, false)
|
err := s.collection.Remove(s.provider, "", ".", "anaconda", s.factory, nil, false)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
_, err = s.collection.ByStoragePrefixDistribution("", ".", "anaconda")
|
_, err = s.collection.ByStoragePrefixDistribution("", ".", "anaconda")
|
||||||
@@ -854,7 +806,7 @@ func (s *PublishedRepoRemoveSuite) TestRemoveRepo3(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublishedRepoRemoveSuite) TestRemoveRepo5(c *C) {
|
func (s *PublishedRepoRemoveSuite) TestRemoveRepo5(c *C) {
|
||||||
err := s.collection.Remove(s.provider, "files:other", "ppa", "osminog", s.factory, nil, false, false)
|
err := s.collection.Remove(s.provider, "files:other", "ppa", "osminog", s.factory, nil, false)
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
_, err = s.collection.ByStoragePrefixDistribution("files:other", "ppa", "osminog")
|
_, err = s.collection.ByStoragePrefixDistribution("files:other", "ppa", "osminog")
|
||||||
|
|||||||
+1
-1
@@ -204,7 +204,7 @@ func (q *FieldQuery) Fast(list PackageCatalog) bool {
|
|||||||
// String interface
|
// String interface
|
||||||
func (q *FieldQuery) String() string {
|
func (q *FieldQuery) String() string {
|
||||||
escape := func(val string) string {
|
escape := func(val string) string {
|
||||||
if strings.ContainsAny(val, "()|,!{} \t\n") {
|
if strings.IndexAny(val, "()|,!{} \t\n") != -1 {
|
||||||
return "'" + strings.Replace(strings.Replace(val, "\\", "\\\\", -1), "'", "\\'", -1) + "'"
|
return "'" + strings.Replace(strings.Replace(val, "\\", "\\\\", -1), "'", "\\'", -1) + "'"
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user