diff --git a/lib/generators/web_git/install_generator.rb b/lib/generators/web_git/install_generator.rb index 465051b..26b4dc3 100644 --- a/lib/generators/web_git/install_generator.rb +++ b/lib/generators/web_git/install_generator.rb @@ -2,24 +2,46 @@ module WebGit class InstallGenerator < Rails::Generators::Base def generate_server + filename = Rails.root.join("config.ru") + log :insert, "Updating config.ru to run apps in parallel." - - contents = <<-RUBY.gsub(/^ /, "") + if File.exists?(filename) && already_installed? + log :identical, "Skipping overrides." + else + contents = <<~RUBY - if Rails.env.development? - map '/git' do - run WebGit::Server + if Rails.env.development? + map '/git' do + run WebGit::Server + end end + + map '/' do + RUBY + + filename = "config.ru" + match_text = "run Rails.application" + + insert_into_file filename, contents, before: match_text + insert_into_file filename, "\nend", after: match_text, force: true + gsub_file filename, match_text, "\t#{match_text}" end - map '/' do\n\t - RUBY + expect_installed = run("which expect") + + unless expect_installed + log :insert, "Installing expect." + run "sudo apt install -y expect" + else + log :identical, "expect already installed." + end + end - filename = "config.ru" - match_text = "run Rails.application" + def already_installed? + filename = Rails.root.join("config.ru") + contents = open(filename).read - insert_into_file filename, contents, before: match_text - insert_into_file filename, "\nend", after: match_text, force: true + contents.match?(/if\s*Rails.env.development\?\s*map\s*'\/git'\s*do\s*run\s*WebGit::Server\s*end\s*end/) end end end diff --git a/lib/scripts/heroku_login.exp b/lib/scripts/heroku_login.exp new file mode 100755 index 0000000..b09899a --- /dev/null +++ b/lib/scripts/heroku_login.exp @@ -0,0 +1,58 @@ +#!/usr/bin/expect -f +# +# This Expect script was generated by autoexpect on Tue Jun 22 17:49:07 2021 +# Expect and autoexpect were both written by Don Libes, NIST. +# +# Note that autoexpect does not guarantee a working script. It +# necessarily has to guess about certain things. Two reasons a script +# might fail are: +# +# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, +# etc.) and devices discard or ignore keystrokes that arrive "too +# quickly" after prompts. If you find your new script hanging up at +# one spot, try adding a short sleep just before the previous send. +# Setting "force_conservative" to 1 (see below) makes Expect do this +# automatically - pausing briefly before sending each character. This +# pacifies every program I know of. The -c flag makes the script do +# this in the first place. The -C flag allows you to define a +# character to toggle this mode off and on. + +set force_conservative 0 ;# set to 1 to force conservative mode even if + ;# script wasn't run conservatively originally +if {$force_conservative} { + set send_slow {1 .1} + proc send {ignore arg} { + sleep .1 + exp_send -s -- $arg + } +} + +# +# 2) differing output - Some programs produce different output each time +# they run. The "date" command is an obvious example. Another is +# ftp, if it produces throughput statistics at the end of a file +# transfer. If this causes a problem, delete these patterns or replace +# them with wildcards. An alternative is to use the -p flag (for +# "prompt") which makes Expect only look for the last line of output +# (i.e., the prompt). The -P flag allows you to define a character to +# toggle this mode off and on. +# +# Read the man page for more info. +# +# -Don + +set email [lindex $argv 0]; +set password [lindex $argv 1]; + +set timeout -1 +spawn heroku login --interactive +match_max 100000 +expect -re {(.|\n)*Enter your login credentials\r} +send -- "$email" +expect -exact "$email" +send -- "\r" +expect -re {(.|\n)*Password:} +send -- "$password" +expect -re {\*.*} +send -- "\r" +expect eof diff --git a/lib/views/status.erb b/lib/views/status.erb index 48bf557..3ce149b 100644 --- a/lib/views/status.erb +++ b/lib/views/status.erb @@ -16,6 +16,29 @@ .commit:hover { color: red; } + .heroku { + background-color: #7952b3; + } + + .btn-heroku { + color: #fff; + background-color: #7952b3; + border-color: #7952b3; + } + + .btn-heroku:hover { + color: #fff; + background-color: #614092; + border-color: #6d48a4; + } + .btn-outline-heroku { + color: #7952b3; + border-color: #7952b3; + background-color: #fff; + } + .border-heroku { + border-color: #7952b3 !important; + } Git Client @@ -43,259 +66,298 @@ <% end %> -
-
-
-

- <% if !@diff.nil? %> - On branch <%= @current_branch %> - <% else %> - git status - <% end %> -

+ -
- <%# if false %> - <% unless @status.include?("nothing to commit, working tree clean") %> -

- You have changes -

- <% @statuses.each do |status| %> - <% filelist = status[:file_list].join("\n") %> - <% if filelist.length > 0 %> - <%= status[:name] %> -
<%= filelist.strip %>
+
+
+
+
+
+

+ <% if !@diff.nil? %> + On branch <%= @current_branch %> + <% else %> + git status <% end %> - <% end %> - - <% if !@diff.nil? %> - <%= @diff %> - <% end %> - -

- What do you want to do? -

+

-
-
-
-
- Commit your changes to the current branch -
- -
-
-
- - -
+
+ <%# if false %> + <% unless @status.include?("nothing to commit, working tree clean") %> +

+ You have changes +

+ <% @statuses.each do |status| %> + <% filelist = status[:file_list].join("\n") %> + <% if filelist.length > 0 %> + <%= status[:name] %> +
<%= filelist.strip %>
+ <% end %> + <% end %> -
- - -
+ <% if !@diff.nil? %> + <%= @diff %> + <% end %> - - -
-
-
+

+ What do you want to do? +

-
-
+
- Switch to a new branch + Commit your changes to the current branch
-
+
- - - + +
-
-
-
-
-
- Discard your changes +
+
+
+
+ Switch to a new branch +
+ +
+
+
+ + +
+ +
+
+
+
-
- - - Discard your changes - +
+
+
+
+ Discard your changes +
+ + +
-
-
- <% else %> + <% else %> -
-
-
-
- Remote: -
- <%= @remotes.first %> -
- -
<%= @status %>
- - <% if @current_branch != "master" %> -
- -
- <% else %> -
- -
- <% end %> -
- -
-

- The last thing you did was: -

+
+
+
+
+ Remote: +
+ <%= @remotes.first %> +
+
<%= @status %>
+ <%# TODO why is this here? %> + <% if @current_branch != "master" %> +
+ +
+ <% else %> +
+ +
+ <% end %> +
+ +
+

+ The last thing you did was: +

-
- <%= @last_commit_message %> -
- +
+ <%= @last_commit_message %> +
+ -
-
- <%= @last_diff_html %> +
+ +
-
-
-
-
    -
  • - New Branch -
  • +
    +
      +
    • + New Branch +
    • -
    • -
      -
      - - -
      - -
      -
    • -
    • - Existing branches -
    • - <% @branches.each do |branch| %> -
    • - <%= branch %> -
      - +
    • - -
      -
      -
      -
    - - <% end %> -
-
+ +
  • + Existing branches +
  • + <% @branches.each do |branch| %> +
  • + <%= branch %> +
    + +
    + +
    +
    + +
    +
    +
  • + <% end %> + +
    +
    + <% end %>
    - <% end %> +
    -
    -
    -
    -
    -
    -

    - History -

    +
    +
    +
    +

    + History +

    -
    -

    Do you want to jump back in time and go down a different path?

    -
    -
    - - -
    - -
    - - -
    +
    +

    Do you want to jump back in time and go down a different path?

    + +
    + + +
    - <% if @changed_files.count > 0 %> - - <% else %> - - - <% end%> - +
    + + +
    + + <% if @changed_files.count > 0 %> + + <% else %> + + + <% end%> + +
    +
    <%= @cli_graph_interactive %>
    +
    -
    <%= @cli_graph_interactive %>
    +
    +
      +
    • + <% if @heroku_auth.empty? %> + Log in + <% else %> + Logged in as: + <%= @heroku_auth %> + <% end %> +
    • + <% if @heroku_auth.empty? %> +
      +
      +
      + + +
      +
      + + +
      + +
      +
      + + <% end %> +
    +
    diff --git a/lib/web_git.rb b/lib/web_git.rb index 78815de..2caa92a 100644 --- a/lib/web_git.rb +++ b/lib/web_git.rb @@ -5,6 +5,7 @@ module WebGit require "active_support" require "web_git/diff" require "web_git/graph" + require "web_git/heroku" require "web_git/string" require "sinatra" require "date" @@ -47,6 +48,7 @@ class Server < Sinatra::Base @current_branch = git.current_branch # g.branch(@current_branch).checkout # maybe? + # TODO use git gem for status @status = `git status` @diff = git.diff @diff = Diff.diff_to_html(git.diff.to_s) @@ -74,6 +76,8 @@ class Server < Sinatra::Base branch_b[:log].last[:date] <=> branch_a[:log].last[:date] end + # TODO heroku stuff + @heroku_auth = WebGit::Heroku.whoami erb :status end @@ -137,6 +141,19 @@ class Server < Sinatra::Base redirect to("/") end + post "/heroku/login" do + email = params[:heroku_email] + password = params[:heroku_password] + + begin + WebGit::Heroku.authenticate(email, password) + set_flash(:notice, "Successfully logged into Heroku.") + rescue => exception + set_flash(:alert, "There was a problem logging into Heroku. #{exception.message}") + end + redirect to("/") + end + protected def git diff --git a/lib/web_git/exceptions.rb b/lib/web_git/exceptions.rb new file mode 100644 index 0000000..cf2b447 --- /dev/null +++ b/lib/web_git/exceptions.rb @@ -0,0 +1,3 @@ +module WebGit + class AuthenticationError < StandardError; end +end diff --git a/lib/web_git/heroku.rb b/lib/web_git/heroku.rb new file mode 100644 index 0000000..53335a0 --- /dev/null +++ b/lib/web_git/heroku.rb @@ -0,0 +1,34 @@ +require 'timeout' +require 'web_git/exceptions' + +module WebGit + class Heroku + def self.authenticate(email, password) + raise ArgumentError.new("Email and password cannot be blank.") if email.blank? || password.blank? + script = File.join( File.dirname(__FILE__), '/../scripts/heroku_login.exp') + + command = "#{script} #{email} #{password}" + rout, wout = IO.pipe + pid = Process.spawn(command, :out => wout) + + begin + status = Timeout.timeout(30) do + _, status = Process.wait2(pid) + wout.close + end + stdout = rout.readlines.join("\n") + rout.close + message = stdout.match(/Error.*\./).to_s + raise WebGit::AuthenticationError.new(message) if stdout.include?("Error") + + rescue Timeout::Error + Process.kill('TERM', script_pid) + raise Timeout::Error.new("Sign in took longer than 30 seconds.") + end + end + + def self.whoami + `heroku whoami`.chomp + end + end +end diff --git a/web_git.gemspec b/web_git.gemspec index aeb390c..32e1e45 100644 --- a/web_git.gemspec +++ b/web_git.gemspec @@ -29,9 +29,11 @@ Gem::Specification.new do |s| "Rakefile", "VERSION", "lib/generators/web_git/install_generator.rb", + "lib/scripts/heroku_login.exp", "lib/views/status.erb", "lib/web_git.rb", "lib/web_git/diff.rb", + "lib/web_git/exceptions.rb", "lib/web_git/graph.rb", "lib/web_git/string.rb", "lib/web_git/version.rb",