aptly-api 0.8.1 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c729ac7d333aee96cfebe50fab52e466ab5a0f40415731fb8b5aa13ce25ca07
4
- data.tar.gz: 40ec80ef71efcf5b210f19db3bfafe00b3aa5d6cb41db4756b4dfb41a6af1baf
3
+ metadata.gz: 1620dd9faac56d2cdc59e3c4fa5071269dfa3fb500ca6837d0c5c2095dfbc793
4
+ data.tar.gz: 9010ab42e434fa472f990a4d8d69a519bbf7989597a9e6c826aae988997d533c
5
5
  SHA512:
6
- metadata.gz: 67731160d86722a903a54a8492ac98d7e98e6ad06d3740a175c54cb0798dbdd749bb14138afdb81f6c325970e9ac14a6daf27a4a9acaa164a56c29d6a757fc0e
7
- data.tar.gz: e70a5147ec2eba41c2d8b99e10f47caaca3c784da1cde20fa95da157374b5fb233f9d1699d40d2697ecc58fbb309bf6ef8a3a1d32eedab42634f865ed92da567
6
+ metadata.gz: 120c7e010476239efb0f3148aaa7871875ec959372d5de59bf29693c2440856f62b5170c6aa9f3d910ae61648a5afc10d8ea88b1283204220e2abd97419d17a5
7
+ data.tar.gz: 719edccb1abff82d097c269631f15b3d56b1cdb809d121bda40c08b6dbe8032a461aa90010241ec7c7e2c0e385a65dbb9668eb226d5fe1120883a88ec6ae43eb
@@ -1,9 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.1
4
- - 2.3.0
5
- - 2.4.0
6
3
  - 2.5.0
7
- before_install:
8
- - gem update --system
9
- - gem install bundler -v 1.10.6
4
+ - 2.6.0
5
+ - 2.7.0
@@ -1,5 +1,50 @@
1
1
  # Change Log
2
2
 
3
+ ## [0.10.1]
4
+ ### Fixed
5
+ - Publishing endpoint escaping no longer creates invalid URIs when the Prefix
6
+ already contains underscores. Prefix=foo_bar is now correctly escaped to
7
+ foo__bar.
8
+ - excon 0.71 is now required as earlier versions had open security issues.
9
+
10
+ ## [0.10.0]
11
+ ### Added
12
+ - `PublishedRepository#from_repositories` publishes repository sources
13
+ into the same prefix.
14
+ - `Aptly.repo` is a new shorthand for `Aptly::Repository.get` to get
15
+ a repository by name when writing code interactively in IRB, or to
16
+ write slightly less verbose code.
17
+
18
+ ### Fixed
19
+ - Documentation fixes.
20
+ - `Connection.HTTP_ACTIONS` is now properly marked private.
21
+
22
+ ## [0.9.1]
23
+ ### Fixed
24
+ - Hint at needing `noRemove: 1` as param when loop adding files (default
25
+ behavior is to remove added files) in the `Files.tmp_upload` documentation.
26
+ - `Connection` properly passes query parameters for post-ish requests now.
27
+ - `Repository.add_file` no longer mangles it's query parameters as they are
28
+ inconsistently cased on the API level.
29
+
30
+ ## [0.9.0]
31
+ ### Added
32
+ - `Files.tmp_upload` is a new convenience wrapper around `#upload` and
33
+ `#delete`. It picks a temporary directory name and uploads the list of files
34
+ to that directory, it then yields the directory name so you can use it as file
35
+ identifier for the files. When the method returns it automatically cleans the
36
+ remote up via `#delete`.
37
+
38
+ ### Changed
39
+ - `Repository.upload` is now based on `Files.tmp_upload`. Functionally
40
+ all remains the same; the temporary directory name on the remote changes.
41
+ - Temporary directory names now include a thread id to reduce the risk of
42
+ conflicts across different threads.
43
+
44
+ ## [0.8.2]
45
+ ### Fixed
46
+ - Temporary files no longer contain characters that trip up the daemon.
47
+
3
48
  ## [0.8.1]
4
49
  ### Changed
5
50
  - Ruby 2.5.0 compatible. Temporary name construction of uploaded files now
data/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  [![Inline docs](http://inch-ci.org/github/KDEJewellers/aptly-api.svg?branch=master)](http://inch-ci.org/github/KDEJewellers/aptly-api)
4
4
  [![Build Status](https://travis-ci.org/KDEJewellers/aptly-api.svg?branch=master)](https://travis-ci.org/KDEJewellers/aptly-api)
5
5
  [![Coverage Status](https://coveralls.io/repos/KDEJewellers/aptly-api/badge.svg?branch=master&service=github)](https://coveralls.io/github/KDEJewellers/aptly-api?branch=master)
6
- [![Dependency Status](https://gemnasium.com/KDEJewellers/aptly-api.svg)](https://gemnasium.com/KDEJewellers/aptly-api)
7
6
  [![Code Climate](https://codeclimate.com/github/KDEJewellers/aptly-api/badges/gpa.svg)](https://codeclimate.com/github/KDEJewellers/aptly-api)
8
7
 
9
8
  ## Installation
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_development_dependency 'bundler', '~> 1.10'
22
+ spec.add_development_dependency 'bundler', '~> 2.0'
23
23
  spec.add_development_dependency 'coveralls', '~> 0.8'
24
24
  spec.add_development_dependency 'minitest', '~> 5.8'
25
25
  spec.add_development_dependency 'rake', '~> 12.0'
@@ -29,5 +29,5 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency 'yard', '~> 0.8'
30
30
 
31
31
  spec.add_dependency 'faraday', '~> 0.9'
32
- spec.add_dependency 'excon', '~> 0.54'
32
+ spec.add_dependency 'excon', '~> 0.71'
33
33
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2015 Harald Sitter <sitter@kde.org>
1
+ # Copyright (C) 2015-2020 Harald Sitter <sitter@kde.org>
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -26,18 +26,27 @@ require 'aptly/tmpname'
26
26
  # Aptly API
27
27
  module Aptly
28
28
  class << self
29
+ # Configures aptly in a block.
29
30
  def configure
30
31
  yield configuration
31
32
  end
32
33
 
34
+ # The global configuration instance.
33
35
  def configuration
34
36
  @configuration ||= Configuration.new
35
37
  end
36
38
 
39
+ # Convenience shorthand for {Repository#get}.
40
+ # @since 0.10.0
41
+ def repo(name, connection = Connection.new, **kwords)
42
+ Repository.get(name, connection, **kwords)
43
+ end
44
+
37
45
  # Publish 1 or more sources into a public repository prefix.
38
46
  # @param sources [Array<Repository>] array of repositories to source
39
- # @param prefix [String] the prefix to publish under (must be escaped see
40
- # {#escape_prefix})
47
+ # @param prefix [String] prefix to publish under (i.e. published repo name).
48
+ # This must be escaped (see {Aptly.escape_prefix})
49
+ # @see Aptly.escape_prefix
41
50
  # @param source_kind [String] the source kind (local or snapshot)
42
51
  # @return [PublishedRepository] newly published repository
43
52
  def publish(sources, prefix = '', source_kind = 'local',
@@ -60,7 +69,7 @@ module Aptly
60
69
  # @return [String] API-safe prefix notation
61
70
  # @since 0.7.0
62
71
  def escape_prefix(prefix_path)
63
- prefix_path.tr('_', '__').tr('/', '_')
72
+ prefix_path.gsub('_', '__').tr('/', '_')
64
73
  end
65
74
  end
66
75
  end
@@ -31,9 +31,10 @@ module Aptly
31
31
  private_constant :GETISH_ACTIONS
32
32
  POSTISH_ACTIONS = %i[post put].freeze
33
33
  private_constant :POSTISH_ACTIONS
34
- HTTP_ACTIONS = GETISH_ACTIONS + POSTISH_ACTIONS
35
34
  WRITE_ACTIONS = (POSTISH_ACTIONS + %i[delete]).freeze
36
35
  private_constant :WRITE_ACTIONS
36
+ HTTP_ACTIONS = GETISH_ACTIONS + POSTISH_ACTIONS
37
+ private_constant :HTTP_ACTIONS
37
38
 
38
39
  CODE_ERRORS = {
39
40
  400 => Errors::ClientError,
@@ -126,12 +127,14 @@ module Aptly
126
127
 
127
128
  def run_postish(action, path, kwords)
128
129
  body = kwords.delete(:body)
130
+ params = kwords.delete(:query)
129
131
  headers = kwords.delete(:headers)
130
132
 
131
133
  body, headers = mangle_post(body, headers, kwords)
132
134
 
133
135
  @connection.send(action, path, body, headers) do |request|
134
136
  setup_request(action, request)
137
+ request.params.update(params) if params
135
138
  end
136
139
  end
137
140
 
@@ -1,3 +1,18 @@
1
+ # Copyright (C) 2015-2018 Harald Sitter <sitter@kde.org>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 3 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library. If not, see <http://www.gnu.org/licenses/>.
15
+
1
16
  module Aptly
2
17
  # Aptly files management.
3
18
  # @see http://www.aptly.info/doc/api/files/
@@ -14,6 +29,38 @@ module Aptly
14
29
  JSON.parse(response.body)
15
30
  end
16
31
 
32
+ # Upload files into a temporary directory on remote.
33
+ # This method expects a block which will be yielded to with the directory
34
+ # name on the remote. The directory will be deleted when this method
35
+ # returns.
36
+ # You'll generally want to use this instead of #upload so you don't have
37
+ # to worry about name collission and clean up.
38
+ #
39
+ # @param files [Array<String>] paths to files to upload
40
+ # @param connection [Connection] connection to use
41
+ # @yield [String] the remote directory name the files were uploaded to
42
+ # @return return value of block
43
+ #
44
+ # @example Can be used to push into multiple repositories with one upload
45
+ # Files.tmp_upload(files) do |d|
46
+ # repos.each { |r| r.add_files(d, noRemove: 1) }
47
+ # end
48
+ #
49
+ # @since 0.9.0
50
+ def tmp_upload(files, connection = Connection.new, **kwords)
51
+ # TODO: 1.0 find out if #upload even has a use case and maybe replace it
52
+ dir = tmp_dir_name
53
+ upload(files, dir, connection, **kwords)
54
+ uploaded = true
55
+ yield dir
56
+ ensure
57
+ # We have an uploaded var here as exceptions raised by upload would
58
+ # still run this, but they may not have the remote file, so our
59
+ # delete request would again cause an error making it harder to spot
60
+ # the orignal problem.
61
+ delete(dir) if uploaded
62
+ end
63
+
17
64
  # Delete files from remote's upload directory.
18
65
  # @param path [String] path to delete (this may be a directory or a file)
19
66
  # @return [nil]
@@ -21,6 +68,13 @@ module Aptly
21
68
  connection.send(:delete, "/files/#{path}", kwords)
22
69
  nil
23
70
  end
71
+
72
+ private
73
+
74
+ def tmp_dir_name
75
+ prefix = "#{to_s.tr(':', '_')}-#{Socket.gethostname}"
76
+ TmpName.dir(prefix)
77
+ end
24
78
  end
25
79
  end
26
80
  end
@@ -42,6 +42,17 @@ module Aptly
42
42
  query: kwords)
43
43
  JSON.parse(response.body).collect { |h| new(connection, h) }
44
44
  end
45
+
46
+ # Publish an array of {Repository} to a prefix.
47
+ # @param repos [Array<Repository>] array of repositories to source
48
+ # @param prefix [String] the prefix to publish under (must be escaped see
49
+ # {.escape_prefix})
50
+ # @return [PublishedRepository] newly published repository
51
+ # @since 0.10.0
52
+ def from_repositories(repos, prefix, **kwords)
53
+ sources = repos.collect { |x| { Name: x.Name } }
54
+ Aptly.publish(sources, prefix, **kwords)
55
+ end
45
56
  end
46
57
 
47
58
  private
@@ -1,11 +1,13 @@
1
1
  module Aptly
2
+ # Abstract "type" of all publishable entities. Publishable entities
3
+ # are everything that can act as Source for a PublishedRepository.
2
4
  module Publishable
3
5
  # Lists all PublishedRepositories self is published in. Namely self must
4
6
  # be a source of the published repository in order for it to appear here.
5
7
  # This method always returns an array of affected published repositories.
6
8
  # If you use this method with a block it will additionally yield each
7
9
  # published repository that would appear in the array, making it a shorthand
8
- # for {Array#each}.
10
+ # for Array#each.
9
11
  # @yieldparam pub [PublishedRepository]
10
12
  # @return [Array<PublishedRepository>]
11
13
  def published_in
@@ -41,8 +41,11 @@ module Aptly
41
41
  # @return [Hash] report data as specified in the API.
42
42
  # FIXME: this should be called file
43
43
  def add_file(path, **kwords)
44
+ # Don't mangle query, the file API is inconsistently using camelCase
45
+ # rather than CamelCase.
44
46
  response = connection.send(:post, "/repos/#{self.Name}/file/#{path}",
45
- query: kwords)
47
+ query: kwords,
48
+ query_mangle: false)
46
49
  hash = JSON.parse(response.body)
47
50
  error = Errors::RepositoryFileError.from_hash(hash)
48
51
  raise error if error
@@ -52,12 +55,9 @@ module Aptly
52
55
  # FIXME: needs to support single files
53
56
  # Convenience wrapper around {Files.upload}, {#add_file} and {Files.delete}
54
57
  def upload(files)
55
- prefix = "#{self.class.to_s.tr(':', '_')}-#{Socket.gethostname}-"
56
- directory = TmpName.make(prefix)
57
- Files.upload(files, directory, connection)
58
- add_file(directory)
59
- ensure
60
- Files.delete(directory, connection)
58
+ Files.tmp_upload(files, connection) do |dir|
59
+ add_file(dir)
60
+ end
61
61
  end
62
62
 
63
63
  # List all packages in the repository
@@ -95,7 +95,9 @@ module Aptly
95
95
 
96
96
  # Convenience wrapper around {Aptly.publish}, publishing this repository
97
97
  # locally and as only source of prefix.
98
- # @param prefix [String] prefix to publish under (i.e. published repo name)
98
+ # @param prefix [String] prefix to publish under (i.e. published repo name).
99
+ # This must be escaped (see {Aptly.escape_prefix})
100
+ # @see Aptly.escape_prefix
99
101
  # @return [PublishedRepository] newly published repository
100
102
  def publish(prefix, **kwords)
101
103
  Aptly.publish([{ Name: self.Name }], prefix, 'local', kwords)
@@ -28,7 +28,7 @@ module Aptly
28
28
  end
29
29
 
30
30
  # Find differences between this and another snapshot
31
- # @param [Snapshot] to diff against
31
+ # @param other_snapshot [Snapshot] to diff against
32
32
  # @return [Array<Hash>] diff between the two snashots
33
33
  def diff(other_snapshot)
34
34
  endpoint = "/snapshots/#{self.Name}/diff/#{other_snapshot.Name}"
@@ -47,7 +47,9 @@ module Aptly
47
47
 
48
48
  # Convenience wrapper around {Aptly.publish}, publishing this snapshot
49
49
  # locally and as only source of prefix.
50
- # @param prefix [String] prefix to publish under (i.e. published snapshot name)
50
+ # @param prefix [String] prefix to publish under (i.e. published repo name).
51
+ # This must be escaped (see {Aptly.escape_prefix})
52
+ # @see Aptly.escape_prefix
51
53
  # @return [PublishedRepository] newly published repository
52
54
  def publish(prefix, **kwords)
53
55
  Aptly.publish([{ Name: self.Name }], prefix, 'snapshot', kwords)
@@ -13,16 +13,22 @@
13
13
  # You should have received a copy of the GNU Lesser General Public
14
14
  # License along with this library. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
+ require 'English'
17
+
16
18
  module Aptly
17
19
  # Helper to generate temporary names
18
20
  module TmpName
19
- def self.make(prefix)
20
- format('%<prefix>s-%<time>s-%<prog>s-%<rand>s',
21
+ # Generate a random temporary directory name.
22
+ # @param prefix [String] arbitrary prefix string to start the name with
23
+ # @return [String] temporary directory name (only safe characters)
24
+ def self.dir(prefix)
25
+ format('%<prefix>s-%<time>s-%<pid>s-%<tid>s-%<rand>s',
21
26
  prefix: prefix,
22
27
  # rubocop:disable Style/FormatStringToken
23
28
  time: Time.now.strftime('%Y%m%d'),
24
29
  # rubocop:enable Style/FormatStringToken
25
- prog: $PROGRAM_NAME,
30
+ pid: $PROCESS_ID,
31
+ tid: Thread.current.object_id,
26
32
  rand: rand(0x100000000).to_s(36))
27
33
  end
28
34
  end
@@ -1,4 +1,5 @@
1
1
  # Aptly API
2
2
  module Aptly
3
- VERSION = '0.8.1'.freeze
3
+ # The loaded version of the gem.
4
+ VERSION = '0.10.1'.freeze
4
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aptly-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harald Sitter
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-01-15 00:00:00.000000000 Z
12
+ date: 2020-10-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '1.10'
20
+ version: '2.0'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '1.10'
27
+ version: '2.0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: coveralls
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -143,14 +143,14 @@ dependencies:
143
143
  requirements:
144
144
  - - "~>"
145
145
  - !ruby/object:Gem::Version
146
- version: '0.54'
146
+ version: '0.71'
147
147
  type: :runtime
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - "~>"
152
152
  - !ruby/object:Gem::Version
153
- version: '0.54'
153
+ version: '0.71'
154
154
  description: REST client for the Aptly API
155
155
  email:
156
156
  - sitter@kde.org
@@ -201,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  - !ruby/object:Gem::Version
202
202
  version: '0'
203
203
  requirements: []
204
- rubyforge_project:
205
- rubygems_version: 2.7.3
204
+ rubygems_version: 3.1.2
206
205
  signing_key:
207
206
  specification_version: 4
208
207
  summary: REST client for the Aptly API