shell_helpers 0.1.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e423354674b7162de244672ab417617837d4667f
4
- data.tar.gz: 36527735c314d40be7389de683688e4446c24961
2
+ SHA256:
3
+ metadata.gz: 6049045c2830e61e0ea865aeb4905e0f4464cdd4b837ee0e7923667e8aae7900
4
+ data.tar.gz: 2ca9a6fceac250538239f8ff3b075d4d2813b02892f7dad411dfad0a8dbfd1e7
5
5
  SHA512:
6
- metadata.gz: 743a7bbaec3fa0511cbba321b847db43233a3c964bc4a03cbd07577c5ef2ae4e5357d98a9906532c5536842f92f10ecddf815904f2e776035533763a3a9b8fb4
7
- data.tar.gz: 023a3e4ce0a45b3cde0c94906ae05ab1d15687531f9425eb93b60fd59d1fd17c3fd6939b629617d92f0520d6083f06b729a3e54e1ae2f3a317ce58c6b80bf03f
6
+ metadata.gz: 809023e14ecf8fc382ce25f107eeeba053573e190fac4030641a496e74306d3f480ef6b4555f5ffb71b9e412bf4f95778c78ab7bdf27efa7a517f92c1239c69c
7
+ data.tar.gz: 6db15aa50cb2ee5d60ee85404a109b00f8106aad9491b993c6aed289f2f23fd838d65124501a617672cf3e9fa06360aef525177199fedaa1b47362622b6a673c
data/.gitignore CHANGED
@@ -1,2 +1,6 @@
1
- doc/
2
- pkg/
1
+ /.bundle
2
+ /.yardoc/
3
+ /Gemfile.lock
4
+ /doc/
5
+ /pkg/
6
+ /vendor/cache/*.gem
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ - 2.3.3
6
+ - 2.2.6
7
+ - 2.1.10
8
+ #- ruby-head
9
+ #- ruby-head-clang
10
+ script: bundle exec rake test
data/.yardopts CHANGED
@@ -1 +1,6 @@
1
- --markup markdown -M kramdown --title "shell_helpers Documentation" --protected
1
+ --markup markdown
2
+ --title "shell_helpers Documentation"
3
+ --protected
4
+ -
5
+ ChangeLog.md
6
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'drain', :github => 'DamienRobert/drain'
5
+
6
+ group :development do
7
+ gem 'kramdown'
8
+ end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Damien Robert
1
+ Copyright © 2015–2018 Damien Robert
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # shell_helpers
2
2
 
3
3
  * [Homepage](https://github.com/DamienRobert/shell_helpers#readme)
4
- * [Gems]("https://rubygems.org/gems/shell_helpers)
5
4
  * [Issues](https://github.com/DamienRobert/shell_helpers/issues)
6
- * [Documentation](http://rubydoc.info/gems/shell_helpers/frames)
5
+ * [Documentation](http://rubydoc.info/gems/shell_helpers)
7
6
  * [Email](mailto:Damien.Olivier.Robert+gems at gmail.com)
8
7
 
8
+ [![Gem Version](https://img.shields.io/gem/v/shell_helpers.svg)](https://rubygems.org/gems/shell_helpers)
9
+ [![Build Status](https://travis-ci.org/DamienRobert/shell_helpers.svg?branch=master)](https://travis-ci.org/DamienRobert/shell_helpers)
10
+
9
11
  ## Description
10
12
 
11
13
  This gem contains a collection of libraries to ease working with the
@@ -23,13 +25,35 @@
23
25
  this functionality from other command parsers than methadone
24
26
  (like [gli](https://github.com/davetron5000/gli)).
25
27
 
28
+ ## Features
29
+
30
+ One of the main feature is an extension of the class `Pathname` with a
31
+ lots of methods to help in shell related task.
32
+
33
+ ## Examples
34
+
35
+ require 'shell_helpers'
36
+ SH::Pathname.new("foo").cp("bar") #calls FileUtils.cp("foo","bar")
37
+ SH::Pathname.new("foo/").on_cp("bar","baz") #copy 'bar' and 'baz' to 'foo/'
38
+ SH::Pathname.new("foo").on_rm(mode: :dangling_symlink) #remove 'foo' only if it is a dangling symlink
39
+ SH::Pathname.new("foo").squel("bar/baz", action: :on_ln_s) #create a symlink foo/bar/baz -> ../../bar/baz
40
+
41
+ #Symlink all files in a directory into another, while preserving the structure
42
+ SH::Pathname.new("foo").squel_dir("bar',action: :on_ln_s)
43
+ #Remove these symlinks
44
+ SH::Pathname.new("foo").squel_dir("bar") {|o,t| o.on_rm(mode: :symlink)}
45
+
46
+ ## Warning
47
+
48
+ For now the API is experimental and some parts are not ready to use!
49
+
26
50
  ## Install
27
51
 
28
52
  $ gem install shell_helpers
29
53
 
30
54
  ## Copyright
31
55
 
32
- Copyright (c) 2015 Damien Robert
56
+ Copyright © 2015–2018 Damien Robert
33
57
 
34
58
  MIT License. See {file:LICENSE.txt} for details.
35
59
 
data/Rakefile CHANGED
@@ -1,20 +1,16 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
1
  require 'rake'
5
2
 
6
3
  begin
7
- gem 'rubygems-tasks', '~> 0.2'
8
4
  require 'rubygems/tasks'
9
-
10
- Gem::Tasks.new
5
+ Gem::Tasks.new(sign: {checksum: true, pgp: true},
6
+ scm: {status: true}) do |tasks|
7
+ tasks.console.command = 'pry'
8
+ end
11
9
  rescue LoadError => e
12
10
  warn e.message
13
- warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
14
11
  end
15
12
 
16
13
  require 'rake/testtask'
17
-
18
14
  Rake::TestTask.new do |test|
19
15
  test.libs << 'test'
20
16
  test.pattern = 'test/**/test_*.rb'
@@ -22,13 +18,12 @@ Rake::TestTask.new do |test|
22
18
  end
23
19
 
24
20
  begin
25
- gem 'yard', '~> 0.8'
26
21
  require 'yard'
27
-
28
- YARD::Rake::YardocTask.new
22
+ YARD::Rake::YardocTask.new
29
23
  rescue LoadError => e
30
24
  task :yard do
31
- abort "Please run `gem install yard` to install YARD."
25
+ warn e.message
32
26
  end
33
27
  end
34
28
  task :doc => :yard
29
+
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ Integrate ptools?
2
+ https://github.com/djberg96/ptools
data/bin/abs_to_rel.rb ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'shell_helpers/pathname'
4
+ require 'shell_helpers/options'
5
+
6
+ opts = Slop.parse(ARGV) do |o|
7
+ o.bool "-v", "--verbose", "verbose"
8
+ o.bool "-t", "--test", "test"
9
+ o.symbol "-m", "--mode", "Conversion mode", default: :rel
10
+ o.string "-b", "--base", "Assume symlinks are relative to this base"
11
+ o.symbol "--base-mode", "Base conversion mode", default: :abs_realdir
12
+ o.on '--help' do
13
+ puts o
14
+ exit
15
+ end
16
+ end
17
+
18
+ pathname=ShellHelpers::Pathname
19
+ if opts[:verbose] and opts[:test]
20
+ pathname=ShellHelpers::Pathname::DryRun
21
+ elsif opts[:verbose] and !opts[:test]
22
+ pathname=ShellHelpers::Pathname::Verbose
23
+ elsif opts[:test]
24
+ pathname=ShellHelpers::Pathname::NoWrite
25
+ end
26
+
27
+ opts.args.each do |l|
28
+ l=pathname.new(l)
29
+ if l.symlink?
30
+ base=(opts[:base]||l.dirname).convert_path(mode: opts[:'base-mode'])
31
+ oldpath=l.readlink
32
+ newpath=l.rel_path_to(oldpath, base: base, mode: opts[:mode])
33
+ if oldpath != newpath
34
+ puts "#{l}: #{oldpath} -> #{newpath}" if opts[:verbose]
35
+ l.on_ln_sf(newpath, dereference: :none)
36
+ else
37
+ puts "#{l}: #{newpath}" if opts[:verbose]
38
+ end
39
+ else
40
+ puts "! #{l} is not a symlink" if opts[:verbose]
41
+ end
42
+ end
data/bin/mv_and_ln.rb ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'shell_helpers/pathname'
4
+ require 'shell_helpers/options'
5
+
6
+ opts = Slop.parse(ARGV) do |o|
7
+ o.bool "-v", "--verbose", "verbose"
8
+ o.int "--verbose-level", "verbose level"
9
+ o.bool "-t", "--test", "test"
10
+ o.symbol "-m", "--mode", "Conversion mode", default: :rel
11
+ o.symbol "--rm", "rm options", default: :noclobber
12
+ o.symbol "--dereference-mode", "dereference mode for dest"
13
+ o.bool "-L", "--dereference", "dereference dest"
14
+ o.bool "-f", "--force", "force remove"
15
+ o.on '--help' do
16
+ puts o
17
+ exit
18
+ end
19
+ end
20
+
21
+ if opts[:force]
22
+ opts[:rm] ||= :all
23
+ else
24
+ opts[:rm] ||= :noclobber
25
+ end
26
+ #dereference-mode can also take the values 'simple' and 'none'
27
+ opts[:"dereference-mode"] ||= opts[:dereference]
28
+
29
+ pathname=ShellHelpers::Pathname
30
+ if opts[:verbose] and opts[:test]
31
+ pathname=ShellHelpers::Pathname::DryRun
32
+ elsif opts[:verbose] and !opts[:test]
33
+ pathname=ShellHelpers::Pathname::Verbose
34
+ elsif opts[:test]
35
+ pathname=ShellHelpers::Pathname::NoWrite
36
+ end
37
+
38
+ *args,dest=opts.args
39
+ dest=pathname.new(dest)
40
+ if args.empty?
41
+ warn "You should specify at least two arguments"
42
+ exit 1
43
+ end
44
+ if args.length > 1 and !dest.directory?
45
+ warn "When specifying more than one target, dest should be a directory"
46
+ exit 1
47
+ end
48
+ args.each do |f|
49
+ f=pathname.new(f)
50
+ t=dest.directory? ? dest+f.basename : dest
51
+ t=f.rel_path_to(t, mode: opts[:mode])
52
+ puts "#{f} -> #{t}" if opts[:verbose]
53
+ dest.on_mv(f, mode: opts[:rm], verbose: opts[:verbose], dereference: opts[:"dereference-mode"]) and f.on_ln_s(t, verbose: opts[:verbose])
54
+ end
data/gemspec.yml CHANGED
@@ -8,8 +8,9 @@ email: Damien.Olivier.Robert+gems@gmail.com
8
8
  homepage: https://github.com/DamienRobert/shell_helpers#readme
9
9
 
10
10
  dependencies:
11
- drain: ~> 0.1
11
+ drain: ~> 0.2
12
12
  development_dependencies:
13
- minitest: ~> 5.0
14
- rubygems-tasks: ~> 0.2
15
- yard: ~> 0.8
13
+ minitest: "~> 5.0"
14
+ rake: "~> 10"
15
+ rubygems-tasks: "~> 0.2"
16
+ yard: "~> 0.8"
data/lib/shell_helpers.rb CHANGED
@@ -1,20 +1,28 @@
1
1
  require 'shell_helpers/version'
2
2
 
3
- require 'shellwords'; require 'pathname'; require 'fileutils'
4
- require 'dr/ruby_ext/core_ext'; require 'dr/ruby_ext/pathname_ext'
3
+ require 'fileutils'
4
+ #require 'dr/ruby_ext/core_ext'
5
5
  #load everything in shell_helpers/*.rb
6
- dir=File.expand_path(File.basename(__FILE__).chomp('.rb'), File.dirname(__FILE__))
7
- Dir.glob(File.expand_path('*.rb',dir)) do |file|
8
- require file
9
- end
6
+ #dir=File.expand_path(File.basename(__FILE__).chomp('.rb'), File.dirname(__FILE__))
7
+ #Dir.glob(File.expand_path('*.rb',dir)) do |file|
8
+ # require file
9
+ #end
10
+ require 'shell_helpers/logger'
11
+ require 'shell_helpers/run'
12
+ require 'shell_helpers/sh'
13
+ require 'shell_helpers/utils'
14
+ require 'shell_helpers/sysutils'
15
+ require 'shell_helpers/export'
16
+ require 'shell_helpers/pathname'
10
17
 
11
- module SH
18
+ module ShellHelpers
12
19
  include Run #run_command, run_output, run_status, run
13
20
  include CLILogging #logger.{debug info warn error fatal}, log_and_do
14
21
  include ExitNow #exit_now!
15
22
  include Sh #sh, sh!
16
- include ShellExport #export
17
- include ShellUtils #find, run_pager
23
+ include Export #export
24
+ include Utils #find, run_pager, rsync...
25
+ include SysUtils #mount, find_devices...
18
26
  extend self
19
27
  #activates debug mode
20
28
  def self.debug(level=Logger::DEBUG)
@@ -22,11 +30,30 @@ module SH
22
30
  Pathname.send(:include, CLILogging)
23
31
  logger.level=(level)
24
32
  end
25
- #including SH::FU to add FileUtils
33
+ #include SH::FU to add FileUtils
26
34
  module FU
27
35
  include ::FileUtils
28
- include ::SH
36
+ include ::ShellHelpers
29
37
  extend self
30
38
  end
39
+
40
+ # #include LogHelper to set up CLILogging with some convenience facilities
41
+ # module LogHelper
42
+ # include CLILogging
43
+ # CLILogging.logger.progname||=$0
44
+ # # #Activates Sh.sh in klass
45
+ # # def self.included(klass)
46
+ # # klass.const_set(:Sh,ShellHelpers::Sh)
47
+ # # end
48
+ # end
31
49
  end
32
50
 
51
+ #for the lazy
52
+ SH=ShellHelpers
53
+
54
+ ## # SHLog.sh to get logging
55
+ ## module SHLog
56
+ ## include ShellHelpers
57
+ ## include ShellHelpers::ShLog
58
+ ## end
59
+
@@ -0,0 +1,169 @@
1
+ require 'dr/ruby_ext/core_ext' #for Hash#keyed_value
2
+ require 'dr/parse/simple_parser'
3
+
4
+ module ShellHelpers
5
+ module Export
6
+ extend self
7
+ ImportError=Class.new(StandardError)
8
+ ExportError=Class.new(StandardError)
9
+
10
+ #export a value for SHELL consumption
11
+ def export_value(v)
12
+ case v
13
+ when String
14
+ return v.shellescape
15
+ when Array
16
+ return "(#{v.map {|i| i.to_s.shellescape}.join(' ')})"
17
+ when Hash
18
+ return "(#{v.map {|k,v| k.to_s.shellescape+" "+v.to_s.shellescape}.join(' ')})"
19
+ when nil
20
+ return ""
21
+ when ->(x){x.respond_to?(:to_a)}
22
+ return export_value(v.to_a)
23
+ when ->(x){x.respond_to?(:to_h)}
24
+ return export_value(v.to_h)
25
+ else
26
+ return v.to_s.shellescape
27
+ end
28
+ end
29
+ def import_value(v, type: String, unquote: true)
30
+ #String === String => false
31
+ case type.to_s
32
+ when "String"
33
+ v.gsub!(/\A['"]+|['"]+\Z/, "") if unquote
34
+ v.to_s
35
+ when "Integer"
36
+ v.to_i
37
+ when "Symbol"
38
+ v.to_sym
39
+ when "Array"
40
+ #v is of the form (ploum plam)
41
+ #TODO: handle quotes in the array
42
+ eval "%w#{v}"
43
+ when "Hash"
44
+ import_value(v, type: Array).each_slice(2).to_h
45
+ end
46
+ end
47
+
48
+ def escape_name(name, prefix:"", upcase: true)
49
+ name=name.to_s
50
+ name=name.upcase if upcase
51
+ (prefix+name).gsub('/','_')
52
+ end
53
+
54
+ #export_variable("ploum","plam") yields ploum="plam"
55
+ def export_variable(name, value, local: false, export: false, prefix:"",upcase:true)
56
+ r=""
57
+ name=escape_name(name,prefix:prefix,upcase:upcase)
58
+ r+="local #{name}\n" if local
59
+ r+="typeset -A #{name}\n" if Hash === value
60
+ r+="#{name}=#{export_value(value)}\n"
61
+ r+="export #{name}\n" if export
62
+ return r
63
+ end
64
+
65
+ def import_variable(namevalue, downcase:true, type: :auto)
66
+ namevalue.match(/(local|export)?\s*(\S*)=(.*)$/) do |m|
67
+ _match,_type,name,value=m.to_a
68
+ name=name.downcase if downcase
69
+ if type == :auto
70
+ if value=~/^\(.*\)$/
71
+ value=import_value(value, type: Array)
72
+ else
73
+ value=import_value(value)
74
+ end
75
+ else
76
+ value=import_value(value, type: type)
77
+ end
78
+ return name, value
79
+ end
80
+ end
81
+
82
+ #from {ploum: plim} return something like
83
+ #PLOUM=plim
84
+ #that can be evaluated by the shell
85
+ def export_variables(hash, local: false, export: false, prefix:"",upcase:true)
86
+ names=hash.keys.map {|s| escape_name(s,prefix:prefix,upcase:upcase)}
87
+ r=""
88
+ r+="local #{names.join(" ")}\n" if local
89
+ hash.each do |k,v|
90
+ r+=export_variable(k,v,prefix:prefix,upcase:upcase)
91
+ end
92
+ r+="export #{names.join(" ")}\n" if export
93
+ return r
94
+ end
95
+
96
+ #export_parse(hash,"name:value")
97
+ #will output name=$(hash[value])
98
+ #special cases: when value = '/' we return the full hash
99
+ # when value ends by /, we return the splitted hash (and name serves
100
+ # as a prefix)
101
+ #Ex: Numenor ~ $ ./mine/00COMPUTERS.rb --export=//
102
+ # HOSTNAME=Numenor;
103
+ # HOSTTYPE=perso;
104
+ # HOMEPATH=/home/dams;...
105
+ # Numenor ~ $ ./mine/00COMPUTERS.rb --export=syst/
106
+ # LAPTOP=true;
107
+ # ARCH=i686;...
108
+ #Remark: in name:value, we don't put name in uppercase
109
+ #But in split hash mode, we put the keys in uppercase (to prevent collisions)
110
+ def export_parse(hash,s)
111
+ r=""
112
+ args=DR::SimpleParser.parse_string(s.to_s)
113
+ args[:values].each do |k,v|
114
+ if v
115
+ name=k.to_s
116
+ else
117
+ #no name given
118
+ v=k.to_s
119
+ if v !='/' && v[-1]=='/'
120
+ #in split mode we don't need the name
121
+ name=""
122
+ else
123
+ #else since no name was given we reuse the variable
124
+ name=v
125
+ name="all" if v=="/"
126
+ end
127
+ end
128
+ if v != '/' && v[-1]=='/'
129
+ all=true
130
+ v=v[0...-1]
131
+ end
132
+ value=hash.keyed_value(v)
133
+ opts=args[:opts][k]
134
+ if all
135
+ r+=export_variables(value, prefix: name, **opts)
136
+ else
137
+ r+=export_variable(name,value, **opts)
138
+ end
139
+ end
140
+ return r
141
+ end
142
+
143
+ def import_parse(s, split_on: :auto, var_separator:'/', inline: false)
144
+ r={}
145
+ if split_on == :auto
146
+ split_on=","
147
+ split_on="\n" if s =~ /\n/
148
+ end
149
+ if s.is_a?(Enumerable)
150
+ instructions=s
151
+ else
152
+ instructions=s.split(split_on)
153
+ end
154
+ instructions.each do |namevalue|
155
+ if inline
156
+ name,value=DR::SimpleParser.parse_namevalue(optvalue,sep:'=')
157
+ else
158
+ name,value=import_variable(namevalue)
159
+ end
160
+ if name
161
+ r.set_keyed_value(name,value, sep: var_separator)
162
+ else
163
+ raise ImportError.new("Cannot parse #{s}")
164
+ end
165
+ end
166
+ r
167
+ end
168
+ end
169
+ end