vimpk 0.1.0 → 0.1.1

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
2
  SHA256:
3
- metadata.gz: 3c7dead9ffe26e414571f4abe1cefd9f4062c7d371fb2a04659c05387af8c5bd
4
- data.tar.gz: 249aad7c6ef651efed1ad2a449a79f0cffdd386973750209a2ff312ebba081e0
3
+ metadata.gz: b51ebecfb9301fe09e702bcb2dfed7efb76ecaf3f21480af3fd75cf6b16f34cf
4
+ data.tar.gz: 2286aac5e850c870cad840020904a1aef54c320b30f861d647dc9b2dbeec0b26
5
5
  SHA512:
6
- metadata.gz: 806ad154df6624026c2055b08290fc300b544df9c8c68873cfadeb81099ec52a714519ac35e690ce2b686bbe541317b28d4ecfd11aeb47d75ef81af30e836378
7
- data.tar.gz: a3d1730a8cb5f1e54f7e26bc991e2263aace1d563610f3259f78acbe96c3c484a3b9d6d86fa2ab5a8ca7fe6c1cbe6f1c3f0758ebd829f4e91f7723409e539167
6
+ metadata.gz: 7c4a3c50e3b85fa7b58ce0cda77de43925a64a1326a67a33f27f9e6fc0eb00954ac8d1b84decb2c31471232c7269d26bfdbb97f23ff25bf54e7b31b1b33b7f75
7
+ data.tar.gz: d71de4cf60fdc354ae6613dfb5bd152becb4bcd50b72e72726afa15c6bb3febe3c2f6d39a2329cf5138a72dc5d6c5ee0dc2d1a9b61c11b2e73a87726b3c81555
data/exe/vimpk CHANGED
@@ -4,4 +4,4 @@ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
4
 
5
5
  require "vimpk"
6
6
 
7
- VimPK::CLI.start(ARGV)
7
+ VimPK::CLI.new(ARGV).call
data/lib/vimpk/cli.rb CHANGED
@@ -2,8 +2,106 @@
2
2
 
3
3
  module VimPK
4
4
  class CLI
5
- def self.start(args)
6
- VimPK::Update.run
5
+ include Colorizer
6
+
7
+ def initialize(args)
8
+ @args = args
9
+ @parser = VimPK::Options.new(args)
10
+ @options = @parser.options
11
+ @command = determine_command
12
+ end
13
+
14
+ def call
15
+ if @command
16
+ send(@command, *@args)
17
+ else
18
+ puts @parser.parser
19
+ end
20
+ end
21
+
22
+ def determine_command
23
+ return nil if @args.empty?
24
+
25
+ case @args.shift&.downcase
26
+ when "i", "install"
27
+ :install_command
28
+ when "u", "update"
29
+ :update_command
30
+ when "rm", "remove"
31
+ :remove_command
32
+ else
33
+ raise "Unknown command: #{name}"
34
+ end
35
+ end
36
+
37
+ def install_command(package = nil)
38
+ time = Time.now
39
+ install = Install.new(package, @options[:path], @options[:pack], @options[:type])
40
+ puts "Installing #{package} to #{install.dest}…"
41
+ install.call
42
+ puts colorize("Installed #{package} to #{install.dest}. Took #{Time.now - time} seconds.", color: :green)
43
+ rescue Git::GitError => e
44
+ puts colorize("Error: #{e.message}", color: :red)
45
+ abort e.output.lines.map { |line| " #{line}" }.join
46
+ rescue Install::PackageExistsError => e
47
+ puts colorize("Error: #{e.message}", color: :red)
48
+ rescue ArgumentError => e
49
+ puts colorize("Error: #{e.message}", color: :red)
50
+ end
51
+
52
+ def update_command
53
+ update = Update.new(@options[:path])
54
+ puts "Updating #{update.plugins.size} packages in #{@options[:path]}…"
55
+ start_time = Time.now
56
+ update.call
57
+
58
+ statuses = {}
59
+
60
+ while (log = update.logs.pop)
61
+ basename = log[:basename]
62
+ statuses[basename] = log[:log]
63
+ end
64
+
65
+ basenames = update.plugins.map { |dir| File.basename(dir) }.sort_by(&:downcase)
66
+
67
+ max_name_length = statuses.keys.map(&:length).max
68
+
69
+ basenames.each do |basename|
70
+ if statuses[basename]
71
+ formatted_name = basename.rjust(max_name_length)
72
+ formatted_status = colorize("Updated!", color: :green)
73
+ puts "#{formatted_name}: #{formatted_status}"
74
+ end
75
+ end
76
+
77
+ if statuses.size < update.jobs.size
78
+ puts "The remaining #{update.jobs.size - statuses.size} plugins are up to date."
79
+ end
80
+
81
+ puts colorize("Finished updating #{update.jobs.size} plugins. Took #{Time.now - start_time} seconds.")
82
+
83
+ if statuses.size.nonzero?
84
+ print "Display diffs? (Y/n) "
85
+
86
+ answer = $stdin.getch
87
+
88
+ if answer.downcase == "y" || answer == "\r"
89
+ puts
90
+ puts "Displaying diffs…"
91
+
92
+ statuses.each do |basename, status|
93
+ puts status.lines.map { |line| "#{basename}: #{colorize_diff line}" }.join
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def remove_command(name = nil)
100
+ Remove.new(name, @options[:path]).call
101
+
102
+ puts colorize("Package #{name} removed.", color: :green)
103
+ rescue ArgumentError, VimPK::Remove::PackageNotFound => e
104
+ abort colorize(e.message, color: :red)
7
105
  end
8
106
  end
9
107
  end
@@ -31,6 +31,10 @@ module VimPK
31
31
  "\e[31m#{text}\e[0m"
32
32
  when :blue
33
33
  "\e[34m#{text}\e[0m"
34
+ when :yellow
35
+ "\e[33m#{text}\e[0m"
36
+ else
37
+ raise ArgumentError, "Unknown color: #{color}"
34
38
  end
35
39
  end
36
40
  end
data/lib/vimpk/git.rb ADDED
@@ -0,0 +1,43 @@
1
+ module VimPK
2
+ module Git
3
+ module_function
4
+
5
+ class GitError < StandardError
6
+ attr_reader :output
7
+
8
+ def initialize(message, output)
9
+ super(message)
10
+ @output = output
11
+ end
12
+ end
13
+
14
+ def branch(dir: Dir.pwd)
15
+ command("rev-parse --abbrev-ref HEAD", dir: dir)
16
+ end
17
+
18
+ def log(branch, dir: Dir.pwd)
19
+ command("log -p --full-diff HEAD..origin/#{branch}", dir: dir)
20
+ end
21
+
22
+ def fetch(branch, dir: Dir.pwd)
23
+ command("fetch origin #{branch}", dir: dir)
24
+ end
25
+
26
+ def pull(dir: Dir.pwd)
27
+ command("pull --rebase", dir: dir)
28
+ end
29
+
30
+ def clone(source, dest, dir: Dir.pwd)
31
+ out = command("clone #{source} #{dest}", dir: dir)
32
+ if $?.exitstatus != 0
33
+ raise GitError.new("Failed to clone #{source} to #{dest}", out)
34
+ end
35
+ end
36
+
37
+ def command(args, dir: Dir.pwd)
38
+ IO.popen("git -C #{dir} #{args}", dir: dir, err: [:child, :out]) do |io|
39
+ io.read.chomp
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ module VimPK
2
+ class Install
3
+ include VimPK::Colorizer
4
+
5
+ PackageExistsError = Class.new(StandardError)
6
+
7
+ attr_reader :dest
8
+
9
+ def initialize(package, path, pack, type)
10
+ @package = package || raise(ArgumentError, "Package name is required")
11
+ @path = path
12
+ @pack = pack
13
+ @type = type
14
+ @dest = File.join(@path, @pack, @type, File.basename(@package))
15
+ @source = "https://github.com/#{package}.git"
16
+ @git = Git
17
+ end
18
+
19
+ def call
20
+ raise PackageExistsError, "Package #{@package} already exists at #{@dest}" if File.exist?(@dest)
21
+
22
+ Git.clone(@source, @dest, dir: @path)
23
+ end
24
+ end
25
+ end
data/lib/vimpk/job.rb CHANGED
@@ -1,34 +1,22 @@
1
1
  module VimPK
2
2
  class Job
3
- def initialize(dir, updates, output)
3
+ def initialize(dir, logs)
4
4
  @dir = dir
5
5
  @basename = File.basename(dir)
6
- @updates = updates
7
- @output = output
6
+ @logs = logs
7
+ @git = Git
8
8
  end
9
9
 
10
10
  def call
11
- branch = git("rev-parse --abbrev-ref HEAD", dir: @dir)
12
- git("fetch origin #{branch}", dir: @dir)
13
- log = git("log -p --full-diff HEAD..origin/#{branch}", dir: @dir)
11
+ branch = Git.branch(dir: @dir)
12
+ Git.fetch(branch, dir: @dir)
13
+ log = Git.log(branch, dir: @dir)
14
14
 
15
- if log.empty?
16
- puts("Already up to date.")
17
- else
18
- git("pull --rebase", dir: @dir)
19
- @updates << {basename: @basename, log: log}
20
- puts "Updated!"
21
- end
22
- end
23
-
24
- def puts(message = "\n")
25
- @output << {@basename => message}
26
- end
27
-
28
- private
15
+ unless log.empty?
16
+ @logs << {basename: @basename, log: log}
29
17
 
30
- def git(command, dir:)
31
- IO.popen("git -C #{dir} #{command}", dir: dir, err: [:child, :out]) { |io| io.read.chomp }
18
+ Git.pull(dir: @dir)
19
+ end
32
20
  end
33
21
  end
34
22
  end
@@ -0,0 +1,65 @@
1
+ require "optparse"
2
+
3
+ module VimPK
4
+ class Options
5
+ attr_reader :options, :parser
6
+
7
+ DEFAULT_PATH = File.expand_path("~/.vim/pack").freeze
8
+ DEFAULT_TYPE = "start".freeze
9
+ DEFAULT_PACK = "plugins".freeze
10
+
11
+ DefaultOptions = Struct.new(:path, :pack, :type)
12
+
13
+ def initialize(args)
14
+ @options = DefaultOptions.new(DEFAULT_PATH, DEFAULT_PACK, DEFAULT_TYPE)
15
+ @parser = OptionParser.new do |parser|
16
+ parser.banner = "Usage: #{parser.program_name} [options] [command [options]"
17
+ parser.separator ""
18
+ parser.separator "Options:"
19
+
20
+ parser.on("--pack=PATH", String, "Name of the pack (#{DEFAULT_PACK})") do |pack|
21
+ @options[:pack] = pack
22
+ end
23
+
24
+ parser.on("--path=PATH", String, "Path to Vim's pack directory (#{DEFAULT_PATH})") do |path|
25
+ path = File.expand_path(path)
26
+ unless File.directory?(path)
27
+ abort("Error: #{path} is not a directory")
28
+ end
29
+ @options[:path] = path
30
+ end
31
+
32
+ parser.on("--opt", "Install package as an optional plugin") do
33
+ @options[:type] = "opt"
34
+ end
35
+
36
+ parser.on("--start", "Install package as a start plugin (default)") do
37
+ @options[:type] = "start"
38
+ end
39
+
40
+ parser.on("-h", "--help", "Show this help message") do
41
+ puts parser
42
+ exit
43
+ end
44
+
45
+ parser.on("-v", "--version", "Show version") do
46
+ puts VimPK::VERSION
47
+ exit
48
+ end
49
+
50
+ parser.separator ""
51
+ parser.separator "Commands:"
52
+ parser.separator " i|install REPO/NAME [--opt|--start] [--pack=PATH] [--path=PATH] Install a package"
53
+ parser.separator " u|update Update all packages"
54
+ parser.separator " rm|remove NAME Remove all occurrences of a package"
55
+
56
+ begin
57
+ parser.permute!(args)
58
+ rescue OptionParser::MissingArgument, OptionParser::InvalidOption => e
59
+ puts e.message
60
+ abort("Use --help for usage information")
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,24 @@
1
+ require "fileutils"
2
+
3
+ module VimPK
4
+ class Remove
5
+ PackageNotFound = Class.new(StandardError)
6
+
7
+ def initialize(name, path)
8
+ @name = name || raise(ArgumentError, "Package name is required")
9
+ @path = path
10
+ end
11
+
12
+ def call
13
+ glob = Dir.glob(File.join(@path, "*", "{start,opt}", @name))
14
+
15
+ if glob.empty?
16
+ raise PackageNotFound, "Package #{@name} not found in #{@path}."
17
+ else
18
+ glob.each do |dir|
19
+ FileUtils.rm_rf(dir)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/vimpk/update.rb CHANGED
@@ -2,71 +2,23 @@ module VimPK
2
2
  class Update
3
3
  include VimPK::Colorizer
4
4
 
5
- def self.run
6
- new.update
7
- end
5
+ attr_reader :jobs, :logs, :plugins
8
6
 
9
- def initialize(path = "~/.vim/pack")
10
- @before = Time.now
7
+ def initialize(path)
11
8
  @pack_dir = File.expand_path(path)
12
- @updates = Queue.new
13
- @output = Queue.new
9
+ @logs = Queue.new
14
10
  @pool = ThreadPool.new
15
- @dirs = Dir.glob(File.join(@pack_dir, "*", "{start,opt}", "*", ".git")).sort
16
- @basenames = @dirs.map { |dir| File.basename(File.dirname(dir)) }
17
- @longest_name = @basenames.map(&:length).max
18
- end
19
-
20
- def format_name(name)
21
- name.rjust(@longest_name)
11
+ @plugins = Dir.glob(File.join(@pack_dir, "*", "{start,opt}", "*", ".git")).sort.map(&File.method(:dirname))
12
+ @jobs = []
22
13
  end
23
14
 
24
- def update
25
- puts "Updating #{@dirs.size} plugins in #{@pack_dir}"
26
-
27
- jobs = @dirs.map do |git_dir|
28
- plugin_dir = File.dirname(git_dir)
29
- @pool.schedule Job.new(plugin_dir, @updates, @output)
15
+ def call
16
+ @jobs = @plugins.map do |dir|
17
+ @pool.schedule Job.new(dir, @logs)
30
18
  end
31
19
 
32
20
  @pool.shutdown
33
- @output.close
34
-
35
- while (message = @output.pop)
36
- case message
37
- when String
38
- Kernel.puts message
39
- when Hash
40
- basename = message.keys.first
41
- message = message.values.first
42
- message = case message
43
- when "Updated!" then colorize(message, color: :green)
44
- when "Already up to date." then colorize(message, color: :blue)
45
- else message
46
- end
47
- puts "#{format_name(basename)}: #{message}"
48
- end
49
- end
50
-
51
- puts
52
- puts colorize("Done updating #{jobs.size} plugins. Took #{Time.now - @before} seconds.")
53
-
54
- if @updates.size.nonzero?
55
- print "Display diffs? (Y/n) "
56
-
57
- answer = $stdin.getch
58
-
59
- if answer.downcase == "y" || answer == "\r"
60
- puts
61
- puts "Displaying diffs…"
62
-
63
- @updates.size.times do
64
- update = @updates.pop
65
- next if update[:log].empty?
66
- puts update[:log].lines.map { |line| "#{format_name(update[:basename])}: #{colorize_diff line}" }.join
67
- end
68
- end
69
- end
21
+ @logs.close
70
22
  end
71
23
  end
72
24
  end
data/lib/vimpk/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module VimPK
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/vimpk.rb CHANGED
@@ -11,8 +11,12 @@ module VimPK
11
11
  class Error < StandardError; end
12
12
 
13
13
  autoload :CLI, "vimpk/cli"
14
- autoload :ThreadPool, "vimpk/thread_pool"
15
- autoload :Job, "vimpk/job"
16
14
  autoload :Colorizer, "vimpk/colorizer"
15
+ autoload :Remove, "vimpk/remove"
16
+ autoload :Git, "vimpk/git"
17
+ autoload :Install, "vimpk/install"
18
+ autoload :Job, "vimpk/job"
19
+ autoload :Options, "vimpk/options"
20
+ autoload :ThreadPool, "vimpk/thread_pool"
17
21
  autoload :Update, "vimpk/update"
18
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vimpk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Usewicz
@@ -26,7 +26,11 @@ files:
26
26
  - lib/vimpk.rb
27
27
  - lib/vimpk/cli.rb
28
28
  - lib/vimpk/colorizer.rb
29
+ - lib/vimpk/git.rb
30
+ - lib/vimpk/install.rb
29
31
  - lib/vimpk/job.rb
32
+ - lib/vimpk/options.rb
33
+ - lib/vimpk/remove.rb
30
34
  - lib/vimpk/thread_pool.rb
31
35
  - lib/vimpk/update.rb
32
36
  - lib/vimpk/version.rb
@@ -39,6 +43,7 @@ metadata:
39
43
  homepage_uri: https://github.com/pusewicz/vimpk
40
44
  source_code_uri: https://github.com/pusewicz/vimpk
41
45
  changelog_uri: https://github.com/pusewicz/vimpk/blob/main/CHANGELOG.md
46
+ github_repo: ssh://github.com/pusewicz/vimpk
42
47
  post_install_message:
43
48
  rdoc_options: []
44
49
  require_paths: