arli 0.9.0 → 1.0.0

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