arli 0.7.0 → 0.8.3

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +0 -2
  4. data/README.md +149 -48
  5. data/arli.gemspec +1 -3
  6. data/docs/arli-in-action.png +0 -0
  7. data/docs/arlifile.png +0 -0
  8. data/exe/arli +5 -1
  9. data/lib/arli.rb +2 -2
  10. data/lib/arli/actions.rb +6 -1
  11. data/lib/arli/actions/action.rb +57 -37
  12. data/lib/arli/actions/dir_name.rb +18 -16
  13. data/lib/arli/actions/git_repo.rb +8 -8
  14. data/lib/arli/actions/move_to_library_path.rb +54 -0
  15. data/lib/arli/actions/{zip_file.rb → unzip_file.rb} +14 -10
  16. data/lib/arli/arli_file.rb +52 -32
  17. data/lib/arli/cli/app.rb +11 -4
  18. data/lib/arli/cli/command_finder.rb +14 -11
  19. data/lib/arli/cli/parser.rb +70 -29
  20. data/lib/arli/cli/parser_factory.rb +105 -50
  21. data/lib/arli/cli/runner.rb +8 -4
  22. data/lib/arli/commands.rb +1 -0
  23. data/lib/arli/commands/base.rb +11 -6
  24. data/lib/arli/commands/bundle.rb +43 -0
  25. data/lib/arli/commands/install.rb +56 -13
  26. data/lib/arli/commands/search.rb +82 -27
  27. data/lib/arli/configuration.rb +37 -18
  28. data/lib/arli/errors.rb +6 -0
  29. data/lib/arli/library.rb +4 -46
  30. data/lib/arli/library/installer.rb +71 -0
  31. data/lib/arli/library/proxy.rb +79 -0
  32. data/lib/arli/lock/file.rb +65 -0
  33. data/lib/arli/lock/formats.rb +4 -0
  34. data/lib/arli/lock/formats/base.rb +26 -0
  35. data/lib/arli/lock/formats/cmake.rb +24 -0
  36. data/lib/arli/lock/formats/json.rb +25 -0
  37. data/lib/arli/lock/formats/text.rb +13 -0
  38. data/lib/arli/lock/formats/yaml.rb +14 -0
  39. data/lib/arli/output.rb +94 -11
  40. data/lib/arli/version.rb +1 -1
  41. metadata +17 -35
  42. data/docs/arli-full.png +0 -0
  43. data/lib/arli/installer.rb +0 -52
@@ -5,23 +5,28 @@ require 'yaml'
5
5
  module Arli
6
6
  class Configuration
7
7
 
8
- DEFAULT_FILENAME = 'Arlifile'.freeze
9
- ACTIONS_WHEN_EXISTS = %i(backup overwrite abort)
10
- ARLI_COMMAND = 'arli'.freeze
8
+ DEFAULT_FILENAME = 'Arlifile'.freeze
9
+ DEFAULT_LOCK_FILENAME = (DEFAULT_FILENAME + '.lock').freeze
10
+ ACTIONS_WHEN_EXISTS = %i(backup overwrite abort)
11
+ ARLI_COMMAND = 'arli'.freeze
12
+ DEFAULT_RESULTS_LIMIT = 100
11
13
 
12
14
  extend Dry::Configurable
13
15
 
14
16
  # These are populated during the parsing of the params
15
17
  setting :runtime do
16
18
  setting :argv
19
+ setting :pwd
17
20
  setting :command do
18
21
  setting :name
19
22
  setting :instance
20
23
  end
21
24
  end
22
25
 
26
+ # Default locations
23
27
  setting :libraries do
24
28
  setting :path, ::Arduino::Library::DefaultDatabase.library_path
29
+ setting :temp_dir
25
30
  end
26
31
 
27
32
  setting :database do
@@ -29,33 +34,47 @@ module Arli
29
34
  setting :url, ::Arduino::Library::DefaultDatabase.library_index_url
30
35
  end
31
36
 
32
- setting :arlifile do
33
- setting :path, ::Dir.pwd
34
- setting :name, ::Arli::Configuration::DEFAULT_FILENAME
37
+ setting :if_exists do
38
+ setting :overwrite, true
39
+ setting :backup, false
40
+ setting :abort, false
35
41
  end
36
42
 
43
+ # Global flags
44
+ setting :debug, ENV['ARLI_DEBUG'] || false
45
+ setting :trace, false
46
+ setting :dry_run, false
47
+ setting :verbose, false
48
+ setting :help, false
49
+ setting :quiet, false
50
+
51
+ # Commands
37
52
  setting :search do
53
+ setting :argument
38
54
  setting :default_field, :name
39
55
  setting :results do
40
- setting :limit, 100
56
+ setting :attrs
57
+ setting :limit, DEFAULT_RESULTS_LIMIT
41
58
  setting :format, :inspect
42
59
  end
43
60
  end
44
61
 
45
- setting :install do
62
+ # Arlifile
63
+ setting :arlifile do
64
+ setting :path, ::Dir.pwd
65
+ setting :name, ::Arli::Configuration::DEFAULT_FILENAME
66
+ setting :lock_name, ::Arli::Configuration::DEFAULT_LOCK_FILENAME
67
+ setting :lock_format, :json
68
+ end
69
+
70
+ setting :bundle do
46
71
  setting :library_names, []
47
- setting :if_exists do
48
- setting :overwrite, true
49
- setting :backup, false
50
- setting :abort, false
51
- end
52
72
  end
53
73
 
54
- setting :debug, ENV['ARLI_DEBUG'] || false
55
- setting :trace, false
56
- setting :verbose, false
57
- setting :help, false
58
- setting :quiet, false
74
+ setting :install do
75
+ setting :library
76
+ end
77
+
59
78
  end
60
79
  end
61
80
 
@@ -6,6 +6,10 @@ module Arli
6
6
 
7
7
  class InvalidSyntaxError < ArliError; end
8
8
 
9
+ class InvalidSearchSyntaxError < InvalidSyntaxError; end
10
+
11
+ class InvalidInstallSyntaxError < InvalidSyntaxError; end
12
+
9
13
  class AbstractMethodCalled < ArliError; end
10
14
 
11
15
  class ArliFileNotFound < ArliError; end
@@ -16,6 +20,8 @@ module Arli
16
20
 
17
21
  class InstallerError < ArliError; end
18
22
 
23
+ class TooManyMatchesError < ArliError; end
24
+
19
25
  class ZipFileError < InstallerError; end
20
26
  end
21
27
  end
@@ -1,50 +1,8 @@
1
- require_relative 'installer'
2
- require_relative 'errors'
3
-
4
1
  module Arli
5
- class Library
6
- attr_accessor :lib, :config, :canonical_dir
7
-
8
- def initialize(lib, config: Arli.config)
9
- self.lib = lib
10
- self.config = config
11
- end
12
-
13
- def install
14
- Arli::Installer.new(self).install
15
- end
16
-
17
- def rm_rf!
18
- FileUtils.rm_rf(dir)
19
- end
20
-
21
- def libraries_home
22
- config.libraries.path
23
- end
24
-
25
- def dir
26
- lib.name.gsub(/ /, '_')
27
- end
28
-
29
- def path
30
- libraries_home + '/' + dir
31
- end
32
-
33
- def canonical_path
34
- libraries_home + '/' + canonical_dir
35
- end
36
-
37
- def exists?
38
- Dir.exist?(path)
39
- end
40
-
41
- def method_missing(method, *args, &block)
42
- if lib && lib.respond_to?(method)
43
- lib.send(method, *args, &block)
44
- else
45
- super(method, *args, &block)
46
- end
47
- end
2
+ module Library
48
3
 
49
4
  end
50
5
  end
6
+
7
+ require_relative 'library/proxy'
8
+ require_relative 'library/installer'
@@ -0,0 +1,71 @@
1
+ require 'forwardable'
2
+ require 'arli'
3
+ require 'arli/actions'
4
+ require_relative 'proxy'
5
+
6
+ module Arli
7
+ module Library
8
+ class Installer
9
+ include ::Arli::Output
10
+
11
+ extend Forwardable
12
+ def_delegators :@library, :exists?
13
+
14
+ attr_accessor :library, :config, :temp_dir
15
+
16
+ def initialize(library, config: Arli.config)
17
+ self.config = config
18
+ self.library = library
19
+ self.temp_dir = Arli.config.libraries.temp_dir
20
+ end
21
+
22
+ def install
23
+ ___ "#{library.name.blue} "
24
+ if library.nil? && library.library.nil?
25
+ ___ ' (no library) '
26
+ fuck
27
+ elsif library.url.nil?
28
+ ___ ' (no url) '
29
+ fuck
30
+ else
31
+ ___ "(#{library.version.green}) " if library.version
32
+ indent_cursor
33
+ actions(library).each do |action|
34
+ run_action(action)
35
+ end
36
+ end
37
+ ___ "\n"
38
+ end
39
+
40
+ def run_action(action_name)
41
+ klass = Arli::Actions.action(action_name)
42
+ if klass
43
+ action = klass.new(library, config: config)
44
+ if action.supported?
45
+ print_action_starting(action_name.to_s) do
46
+ action.run!
47
+ end
48
+ puts if verbose?
49
+ else
50
+ print_action_failure("unsupported", "missing pre-requisites: #{klass.command_name.bold.yellow} did not succeed")
51
+ end
52
+ else
53
+ print_action_failure("#{action_name.red} not found")
54
+ end
55
+ end
56
+
57
+ def verbose?
58
+ config.verbose
59
+ end
60
+
61
+ def actions(library)
62
+ actions = []
63
+ # First, how do we get the library?
64
+ actions << ((library.url =~ /\.zip$/i) ? :unzip_file : :git_repo)
65
+ actions << :dir_name
66
+ actions << :move_to_library_path
67
+ actions.flatten
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,79 @@
1
+ require_relative 'installer'
2
+ require 'arli/errors'
3
+
4
+ module Arli
5
+ module Library
6
+ # Represents a wrapper around Arduino::Library::Model instance
7
+ # and decorates with a few additional helpers.
8
+ class Proxy
9
+ attr_accessor :lib,
10
+ :lib_dir,
11
+ :canonical_dir,
12
+ :config
13
+
14
+ def initialize(lib, config: Arli.config)
15
+ self.lib = lib
16
+ self.config = config
17
+ self.lib_dir = lib.name.gsub(/ /, '_')
18
+ end
19
+
20
+ def install
21
+ installer.install
22
+ end
23
+
24
+ def installer
25
+ @installer ||= Installer.new(self)
26
+ end
27
+
28
+ def libraries_home
29
+ config.libraries.path
30
+ end
31
+
32
+ def temp_dir
33
+ config.libraries.temp_dir
34
+ end
35
+
36
+ def dir
37
+ canonical_dir || lib_dir
38
+ end
39
+
40
+ def path
41
+ libraries_home + '/' + dir
42
+ end
43
+
44
+ def temp_path
45
+ temp_dir + '/' + dir
46
+ end
47
+
48
+ def exists?
49
+ Dir.exist?(path)
50
+ end
51
+
52
+ # Formats
53
+ def to_s_short
54
+ "#{lib.name.bold.blue} (#{lib.version.yellow}), by #{lib.author.magenta}"
55
+ end
56
+
57
+ def to_s_json
58
+ puts lib.to_json
59
+ end
60
+
61
+ def to_s_long
62
+ "#{lib.name.bold.blue} (#{lib.version.yellow}), by #{lib.author.magenta}}\n\t#{lib.description}"
63
+ end
64
+
65
+ def to_s_pretty(lib, **options)
66
+ "#{lib.name.bold.blue} (#{lib.version.yellow}), by #{lib.author.magenta}"
67
+ end
68
+
69
+ def method_missing(method, *args, &block)
70
+ if lib && lib.respond_to?(method)
71
+ lib.send(method, *args, &block)
72
+ else
73
+ super(method, *args, &block)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,65 @@
1
+ require 'arli'
2
+ require 'yaml'
3
+ require 'forwardable'
4
+ require 'arduino/library'
5
+ require 'hashie/mash'
6
+
7
+ require_relative 'formats'
8
+
9
+ module Arli
10
+ module Lock
11
+ class File
12
+ attr_accessor :lock_file_path,
13
+ :config,
14
+ :formatter,
15
+ :file,
16
+ :format
17
+
18
+ def initialize(config: Arli.config)
19
+ self.config = config
20
+ self.lock_file_path = "#{config.arlifile.path}/#{config.arlifile.lock_name}"
21
+ self.format = config.arlifile.lock_format
22
+ self.formatter = set_formatter(format)
23
+ self.file = ::File.open(lock_file_path, 'w')
24
+
25
+ append(formatter.header)
26
+ end
27
+
28
+ def lock(*libraries)
29
+ libraries.each do |lib|
30
+ append(formatter.format(lib))
31
+ end
32
+ end
33
+
34
+ def lock!(*args)
35
+ lock(*args)
36
+ ensure
37
+ close
38
+ end
39
+
40
+ def close
41
+ append(formatter.footer)
42
+ ensure
43
+ file.close
44
+ FileUtils.cp(lock_file_path, "#{lock_file_path}.#{format}")
45
+ end
46
+
47
+ def append(line = nil)
48
+ return unless line
49
+ line.end_with?("\n") ? file.print(line) : file.puts(line)
50
+ end
51
+
52
+ private
53
+
54
+ def set_formatter(format)
55
+ klass = format.to_s.capitalize.to_sym
56
+ klazz = ::Arli::Lock::Formats.const_get(klass)
57
+ klazz.new(self)
58
+ rescue NameError
59
+ raise Arli::Errors::ArliError,
60
+ "invalid format #{format}, Arli::Lock::Formats::#{klass} does not exist"
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,4 @@
1
+ require_relative 'formats/cmake'
2
+ require_relative 'formats/json'
3
+ require_relative 'formats/yaml'
4
+ require_relative 'formats/text'
@@ -0,0 +1,26 @@
1
+
2
+ module Arli
3
+ module Lock
4
+ module Formats
5
+ class Base
6
+ attr_accessor :lock_file
7
+
8
+ def initialize(lock_file)
9
+ self.lock_file = lock_file
10
+ end
11
+
12
+ # Optional header
13
+ def header
14
+ end
15
+
16
+ def format(library)
17
+ raise Arli::Errors::AbstractMethodCalled, "#format on Base"
18
+ end
19
+
20
+ # Optional footer
21
+ def footer
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'base'
2
+
3
+ module Arli
4
+ module Lock
5
+ module Formats
6
+ class Cmake < Base
7
+
8
+ def header
9
+ "# vi:syntax=cmake\n" +
10
+ "set(ARLI_LIBRARIES)"
11
+ end
12
+
13
+ def format(library)
14
+ "# Library #{library.name}, version #{library.version}, url: #{library.url}\n" +
15
+ "prepend(ARDUINO_ARLI_LIBS ${ARDUINO_ARLI_LIBS} #{library.canonical_dir})"
16
+ end
17
+
18
+ def footer
19
+ "set(ARLI_LIBRARIES $ARLI_LIBRARIES PARENT_SCOPE)"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'base'
2
+
3
+ module Arli
4
+ module Lock
5
+ module Formats
6
+ class Json < Base
7
+ attr_accessor :hash
8
+
9
+ def header
10
+ self.hash = {}
11
+ nil
12
+ end
13
+
14
+ def format(library)
15
+ hash[library.canonical_dir] = library.to_hash
16
+ nil
17
+ end
18
+
19
+ def footer
20
+ JSON.pretty_generate(hash)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end