arli 0.9.0 → 1.0.0

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.
data/Rakefile CHANGED
@@ -7,8 +7,11 @@ def shell(*args)
7
7
  system(args.join(' '))
8
8
  end
9
9
 
10
+ task :clean do
11
+ shell('rm -rfv pkg/ tmp/ coverage/' )
12
+ end
13
+
10
14
  task :permissions do
11
- shell('rm -rf pkg/ tmp/ coverage/' )
12
15
  shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
13
16
  shell("find . -type d -exec chmod o+x,g+x {} \\;")
14
17
  end
@@ -16,8 +19,8 @@ end
16
19
  task :build => :permissions
17
20
 
18
21
  YARD::Rake::YardocTask.new(:doc) do |t|
19
- t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE)
20
- t.options.unshift('--title','"Sym Symmetric Key Encryption for Your Data"')
22
+ t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE.txt)
23
+ t.options.unshift('--title','Arli The Missing Arduino Library Manager')
21
24
  t.after = ->() { exec('open doc/index.html') }
22
25
  end
23
26
 
@@ -5,9 +5,11 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'arli/version'
6
6
 
7
7
  Arli::DESCRIPTION = <<-eof
8
- This is a command-line installer of any number of dependent Github
9
- projects, or libraries. Arli was created to offer Arduino-based projects
10
- an easy to use and consistent library manager.
8
+ This is an Arduino Library manager, compatible with the "arduino-cmake" project.
9
+ Arli offers a powerful command-line tool to manage any number of dependent Github
10
+ projects, or official Arduino libraries. Arli was created to offer Arduino-based
11
+ projects of moderate to high complexity an easy way to reference external libraries
12
+ and install them at build time, instead of committing them into the project repo.
11
13
  eof
12
14
 
13
15
  Gem::Specification.new do |spec|
@@ -29,20 +31,20 @@ Gem::Specification.new do |spec|
29
31
  spec.require_paths = ['lib']
30
32
 
31
33
  spec.add_dependency 'arduino-library', '~> 0.5.4'
32
- spec.add_dependency 'colored2'
33
34
  spec.add_dependency 'awesome_print'
34
- spec.add_dependency 'hashie'
35
- spec.add_dependency 'dry-types'
36
- spec.add_dependency 'dry-struct'
35
+ spec.add_dependency 'colored2'
37
36
  spec.add_dependency 'dry-configurable'
37
+ spec.add_dependency 'dry-struct'
38
+ spec.add_dependency 'dry-types'
39
+ spec.add_dependency 'hashie'
40
+ spec.add_dependency 'require_dir'
38
41
  spec.add_dependency 'tty-cursor'
39
42
 
40
-
41
- spec.add_development_dependency 'yard'
42
- spec.add_development_dependency 'simplecov'
43
+ spec.add_development_dependency 'aruba'
43
44
  spec.add_development_dependency 'bundler', '~> 1.15'
44
45
  spec.add_development_dependency 'rake', '~> 10.0'
45
46
  spec.add_development_dependency 'rspec', '~> 3.0'
46
47
  spec.add_development_dependency 'rspec-its'
47
- spec.add_development_dependency 'aruba'
48
+ spec.add_development_dependency 'simplecov'
49
+ spec.add_development_dependency 'yard'
48
50
  end
Binary file
@@ -1,5 +1,13 @@
1
+ require 'require_dir'
2
+
3
+ module Arli
4
+ extend RequireDir
5
+ init __FILE__
6
+ end
7
+
1
8
  require 'arduino/library'
2
9
  require 'arli/helpers/inherited'
10
+ require 'arli/helpers/system_commands'
3
11
  require 'arli/version'
4
12
  require 'arli/extensions'
5
13
  require 'arli/errors'
@@ -1,7 +1,12 @@
1
1
  require_relative 'action'
2
+ require_relative '../helpers/system_commands'
3
+
2
4
  module Arli
3
5
  module Actions
4
6
  class GitRepo < Action
7
+
8
+ include ::Arli::Helpers::SystemCommands
9
+
5
10
  description 'Fetches or updates remote git repositories'
6
11
  check_command 'git --version'
7
12
  check_pattern 'git version'
@@ -19,21 +24,6 @@ module Arli
19
24
  "git clone -v #{library.url} #{library.dir} 2>&1"
20
25
  end
21
26
 
22
- protected
23
-
24
- # @param <String> *args — list of arguments or a single string
25
- def run_system_command(*args)
26
- cmd = args.join(' ')
27
- raise 'No command to run was given' unless cmd
28
- info("\n" + cmd.green) if Arli.debug?
29
- o, e, s = Open3.capture3(cmd)
30
- info("\n" + o) if o if Arli.debug?
31
- info("\n" + e.red) if e && Arli.debug?
32
- rescue Exception => e
33
- error "Error running [#{args.join(' ')}]\n" +
34
- "Current folder is [#{Dir.pwd.yellow}]", e
35
- raise e
36
- end
37
27
  end
38
28
  end
39
29
  end
@@ -1,15 +1,17 @@
1
1
  require_relative 'action'
2
+ require_relative '../helpers/system_commands'
2
3
 
3
4
  module Arli
4
5
  module Actions
5
6
  class MoveToLibraryPath < Action
7
+
6
8
  description 'Moves the downloaded library to the proper path, optionally creating a backup'
7
9
 
10
+ include ::Arli::Helpers::SystemCommands
11
+
8
12
  def execute
9
13
  Dir.chdir(config.runtime.pwd) do
10
-
11
14
  handle_preexisting_folder(path) if exists?
12
-
13
15
  if Dir.exist?(temp_path) && !Dir.exist?(path)
14
16
  FileUtils.mkdir_p(File.dirname(path))
15
17
  ___ "current: #{Dir.pwd.yellow}\ntemp_path: #{temp_path.yellow}\nlibrary_path: #{path.yellow}\n" if debug?
@@ -23,32 +25,6 @@ module Arli
23
25
  end
24
26
  end
25
27
  end
26
-
27
- private
28
-
29
- def handle_preexisting_folder(to)
30
- if Dir.exist?(to)
31
- if abort?
32
- raise ::Arli::Errors::LibraryAlreadyExists, "Directory #{to} already exists"
33
- elsif backup?
34
- backup!(to)
35
- elsif overwrite?
36
- FileUtils.rm_rf(to)
37
- end
38
- end
39
- end
40
-
41
- def backup!(p)
42
- if Dir.exist?(p)
43
- backup_path = "#{p}.arli-backup-#{Time.now.strftime('%Y%m%d%H%M%S')}"
44
- FileUtils.mv(p, backup_path)
45
- print_target_dir(backup_path, 'backed up')
46
- if verbose?
47
- ___ "\nNOTE: path #{p.blue} has been backed up to #{backup_path.bold.green}\n"
48
- end
49
- end
50
- end
51
-
52
28
  end
53
29
  end
54
30
  end
@@ -18,9 +18,10 @@ module Arli
18
18
  include ::Arli::Library
19
19
 
20
20
  attr_accessor :dependencies,
21
- :parsed_data,
21
+ :arlifile_hash,
22
22
  :arlifile_path,
23
- :config
23
+ :config,
24
+ :device
24
25
 
25
26
  def initialize(config: Arli.config, libraries: [])
26
27
  self.config = config
@@ -29,15 +30,7 @@ module Arli
29
30
 
30
31
  self.config.libraries.temp_dir ||= Dir.mktmpdir
31
32
 
32
- if parsed_data
33
- if parsed_data.libraries_path
34
- self.config.libraries.path = parsed_data.libraries_path
35
- end
36
-
37
- if parsed_data.lock_format
38
- Arli.config.arlifile.lock_format = parsed_data.lock_format
39
- end
40
- end
33
+ configure_via_arlifile!(arlifile_hash)
41
34
  end
42
35
 
43
36
  alias libraries dependencies
@@ -50,6 +43,14 @@ module Arli
50
43
 
51
44
  private
52
45
 
46
+ def configure_via_arlifile!(mash)
47
+ if mash
48
+ config.libraries.path = mash.libraries_path if mash.libraries_path
49
+ config.arlifile.lock_format = mash.lock_format if mash.lock_format
50
+ self.device = mash.device if mash.device
51
+ end
52
+ end
53
+
53
54
  def within_temp_path(&block)
54
55
  within_path(Arli.config.libraries.temp_dir, &block)
55
56
  end
@@ -80,15 +81,17 @@ module Arli
80
81
  end
81
82
 
82
83
  def parse_yaml_file
83
- self.parsed_data = Hashie::Mash.new(
84
+ self.arlifile_hash = Hashie::Mash.new(
84
85
  Hashie::Extensions::SymbolizeKeys.symbolize_keys(
85
86
  ::YAML.load(
86
- ::File.read(
87
- self.arlifile_path)
87
+ ::File.read(self.arlifile_path)
88
88
  )
89
89
  )
90
90
  )
91
- parsed_data.dependencies.map {|lib| make_lib(lib)}
91
+
92
+ config.arlifile.hash = arlifile_hash
93
+
94
+ arlifile_hash.dependencies.map {|lib| make_lib(lib)}
92
95
  end
93
96
  end
94
97
  end
@@ -52,7 +52,7 @@ module Arli
52
52
  end
53
53
 
54
54
  def instantiate_command
55
- self.command_name = detect_command unless command_name
55
+ self.command_name ||= detect_command
56
56
  begin
57
57
  name = command_name.to_s.capitalize.to_sym
58
58
  command_class = ::Arli::Commands.const_get(name)
@@ -97,9 +97,27 @@ module Arli
97
97
  option_search_attributes
98
98
  end
99
99
 
100
- def option_if_exists
100
+ def option_generate
101
+ on('-w', '--workspace DIR',
102
+ 'a top-level folder under which the project will be created',
103
+ 'Default is the current folder.' + "\n\n") do |v|
104
+ config.generate.workspace = v
105
+ end
106
+
107
+ # on('-L', '--libs "LIBS"',
108
+ # 'Comma separated list of library names, or name ',
109
+ # 'substrings, to be searched for and added to the ',
110
+ # 'initial Arlifile. Multiple matches are added anyway',
111
+ # 'while no matches are skipped' + "\n\n") do |v|
112
+ # config.generate.libs = v.split(',')
113
+ # end
114
+
115
+ option_if_exists('project')
116
+ end
117
+
118
+ def option_if_exists(what = 'library')
101
119
  on('-e', '--if-exists ACTION',
102
- 'If a library folder already exists, by default',
120
+ "If a #{what} folder already exists, by default",
103
121
  'it will be overwritten or updated if possible.',
104
122
  'Alternatively you can either ' + 'abort'.bold.blue + ' or ' + 'backup'.bold.blue
105
123
  ) do |v|
@@ -115,23 +133,19 @@ module Arli
115
133
 
116
134
  def option_help(commands: false, command_name: nil)
117
135
  common_help_options
118
-
119
136
  on('-h', '--help', 'prints this help') do
120
137
  ::Arli.config.help = true
121
138
 
122
139
  command_hash = output_command_description(command_name)
123
-
124
- output_help
140
+ output_examples(command_hash[:examples]) if command_hash && command_hash[:examples]
125
141
  output_command_help if commands
142
+ output_help
126
143
 
127
- if command_hash && command_hash[:examples]
128
- output_examples(command_hash[:examples])
129
- else
130
- print_version_copyright
131
- end
144
+ print_version_copyright
132
145
  end
133
146
  end
134
147
 
148
+
135
149
  def option_search_attributes
136
150
  on('-A', '--print-attrs', 'prints full list of available library',
137
151
  'attributes that can be used in search strings.', ' ') do
@@ -240,12 +254,12 @@ See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yell
240
254
  if command_hash.description
241
255
  header 'Description'
242
256
  if command_hash.sentence
243
- output indent + command_hash.sentence.bold
257
+ output indent + command_hash.sentence.bold.blue
244
258
  output ''
245
259
  end
246
260
 
247
261
  text = Array(command_hash[:description]).flatten.join(' ')
248
- output text.reformat_wrapped(width = 70, indent_with = 8)
262
+ output text.reformat_wrapped(width = 70, indent_with = 4).yellow.dark
249
263
  end
250
264
  end
251
265
 
@@ -75,6 +75,38 @@ module Arli
75
75
  }
76
76
  }),
77
77
 
78
+ generate: Hashie::Mash.new(
79
+ {
80
+ sentence: 'Generates a new Arduino project with Arlifile',
81
+
82
+ description: %Q[This will create a new project folder, a source file, and an Arlifile
83
+ based on the template project repo defined in the config file. At the moment
84
+ only arduino-cmake is supported as the build environment as it's the one that
85
+ provides the widest choice of developer IDEs to use for programming your project.
86
+ You can use Vim or Emacs, Atom, CLion, Eclipse, Visual Studio, or just plain
87
+ command line to build and upload your project. Some knowledge of CMake is
88
+ helpful.
89
+ ],
90
+ examples: [
91
+ { desc: 'Creates a new project in the specified folder. Default is current dir.',
92
+ cmd: 'arli generate MyClock --workspace ~/Documents/Arduino/Sketches' },
93
+
94
+ { desc: 'Creates a folder "Blinker" in the current directory',
95
+ cmd: %Q{arli generate Blinker } },
96
+
97
+ { desc: 'Populate initial Arlifile with the libs provided',
98
+ cmd: %Q{arli generate Weather --libs 'Adafruit Unified Sensor,Adafruit GFX Library,Time' } },
99
+ ],
100
+
101
+ parser: -> (command_name) {
102
+ make_parser(command_name) do |parser|
103
+ parser.banner = usage_line 'generate' + ' project-name '.magenta
104
+ parser.option_generate
105
+ parser.option_help(command_name: command_name)
106
+ end
107
+ }
108
+ }),
109
+
78
110
  bundle: Hashie::Mash.new(
79
111
  {
80
112
  sentence: 'Installs all libraries specified in Arlifile',
@@ -145,7 +177,7 @@ module Arli
145
177
  def global_usage(command)
146
178
  'Usage:'.magenta.bold +
147
179
  "\n " + arli_command + ' options '.yellow +
148
- "\n " + arli_command + ' ' + ((command || 'command')).green + ' [ options ] '.yellow + "\n"
180
+ "\n " + arli_command + ' ' + ((command || 'command')).cyan.bold + ' [ options ] '.yellow + "\n"
149
181
  end
150
182
 
151
183
  def arli_command
@@ -154,7 +186,7 @@ module Arli
154
186
 
155
187
  def command_usage(command)
156
188
  'Usage:'.magenta.bold +
157
- "\n " + arli_command + ' ' + command.green + ' [options]'.yellow + "\n\n" +
189
+ "\n " + arli_command + ' ' + command.bold.cyan + ' [options]'.yellow + "\n\n" +
158
190
  'Options'.magenta.bold
159
191
  end
160
192
 
@@ -1,5 +1,6 @@
1
+ require 'arli'
1
2
  require 'arli/cli/app'
2
- require 'pp'
3
+
3
4
  module Arli
4
5
  module CLI
5
6
  # For the reasons this file is the way it is, please refer to
@@ -3,7 +3,5 @@ module Arli
3
3
  end
4
4
  end
5
5
 
6
- require_relative 'commands/base'
7
- require_relative 'commands/search'
8
- require_relative 'commands/bundle'
9
- require_relative 'commands/install'
6
+
7
+ Arli.dir('arli/commands')
@@ -15,7 +15,7 @@ module Arli
15
15
  def setup
16
16
  super
17
17
  self.arlifile = Arli::ArliFile.new(config: config)
18
- self.lock_file = Arli::Lock::File.new(config: config)
18
+ self.lock_file = Arli::Lock::File.new(config: config, arlifile: arlifile)
19
19
  end
20
20
 
21
21
  def params
@@ -0,0 +1,122 @@
1
+ require 'json'
2
+ require 'arli'
3
+ require 'net/http'
4
+ require_relative 'base'
5
+ require_relative '../arli_file'
6
+ require_relative '../helpers/system_commands'
7
+ require 'forwardable'
8
+ module Arli
9
+ module Commands
10
+ class Generate < Base
11
+ include ::Arli::Helpers::SystemCommands
12
+
13
+ extend Forwardable
14
+ def_delegators :@settings, :project_name, :project_name=, :workspace, :workspace=, :libs, :libs=, :template_repo
15
+
16
+ attr_accessor :settings, :dir
17
+
18
+
19
+ def setup
20
+ config.generate.project_name = config.runtime.argv.first
21
+
22
+ self.settings = config.generate
23
+
24
+ raise ::Arli::Errors::RequiredArgumentsMissing, 'Project name is required' unless project_name
25
+ raise ::Arli::Errors::RequiredArgumentsMissing, 'Template Repo is missing' unless template_repo
26
+
27
+ self.dir = settings.workspace + '/' + project_name
28
+ handle_preexisting_folder(dir) if Dir.exist?(dir)
29
+ FileUtils.mkdir_p(workspace) unless Dir.exist?(workspace)
30
+ end
31
+
32
+ def run
33
+ Dir.chdir(workspace) do
34
+ run_system_command "git clone -v #{template_repo} #{project_name} 2>&1"
35
+ Dir.chdir(project_name) do
36
+ FileUtils.rm_rf('.git')
37
+ run_system_command 'git init .'
38
+ run_system_command 'bin/setup'
39
+ configure_template!
40
+ rename_files!
41
+ end
42
+ end
43
+ end
44
+
45
+ def additional_info
46
+ "Generating project #{project_name.bold.green} into #{workspace.bold.yellow}..."
47
+ end
48
+
49
+ private
50
+
51
+ def rename_files!
52
+ Dir.chdir('src') do
53
+ FileUtils.mv('MyProject.cpp', "#{project_name}.cpp")
54
+ run_system_command "sed -i 's/MyProject/#{project_name}/g' CMakeLists.txt"
55
+ end
56
+ end
57
+
58
+ def configure_template!
59
+ File.open('README.md', 'w') do |f|
60
+ f.write <<-EOF
61
+
62
+ # #{project_name}
63
+
64
+ Please refer to the README for the template project, available here:
65
+ [arli-cmake](#{template_repo}).
66
+
67
+ ## Usage
68
+
69
+ Let's cd into the project folder:
70
+
71
+ ```bash
72
+ cd #{project_name}
73
+ ```
74
+
75
+ The directory structure should look as follows:
76
+
77
+ ```
78
+ #{project_name}
79
+ |
80
+ |__ bin/
81
+ | |___ setup
82
+ | |___ build
83
+ |
84
+ |__ cmake/
85
+ | |___ Arli.cmake
86
+ | |___ ArduinoToolchain.cmake <———— provided by arduino-cmake project
87
+ | |___ Platform/ <———— provided by arduino-cmake project
88
+ |
89
+ |__ src/
90
+ | |___ Arlifile
91
+ | |___ CMakeLists.txt
92
+ | |___ #{project_name}.cpp
93
+ |
94
+ |__ example/
95
+ |___ Arlifile
96
+ |___ CMakeLists.txt
97
+ |___ Adafruit7SDisplay.cpp
98
+ ```
99
+
100
+ You might need to run `bin/setup` first to ensure you have all the dependencies.
101
+
102
+ Once you do that, you can build any of the source folders (i.e. either `src` or `example`) by
103
+ running `bin/build src` or `bin/build example`.
104
+
105
+ ### Building Manually
106
+
107
+ The process to build and upload manually is super simple too:
108
+
109
+ ```bash
110
+ cd src
111
+ rm -rf build && mkdir build && cd build
112
+ cmake ..
113
+ make
114
+ make upload
115
+ ```
116
+
117
+ EOF
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end