aptly-api 0.8.1 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
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