githug 0.0.9

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.
Files changed (91) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/README.md +90 -0
  5. data/Rakefile +1 -0
  6. data/bin/githug +4 -0
  7. data/githug.gemspec +27 -0
  8. data/levels/add.rb +17 -0
  9. data/levels/blame.rb +20 -0
  10. data/levels/blame/.githug/COMMIT_EDITMSG +1 -0
  11. data/levels/blame/.githug/HEAD +1 -0
  12. data/levels/blame/.githug/config +5 -0
  13. data/levels/blame/.githug/description +1 -0
  14. data/levels/blame/.githug/hooks/applypatch-msg.sample +15 -0
  15. data/levels/blame/.githug/hooks/commit-msg.sample +24 -0
  16. data/levels/blame/.githug/hooks/post-commit.sample +8 -0
  17. data/levels/blame/.githug/hooks/post-receive.sample +15 -0
  18. data/levels/blame/.githug/hooks/post-update.sample +8 -0
  19. data/levels/blame/.githug/hooks/pre-applypatch.sample +14 -0
  20. data/levels/blame/.githug/hooks/pre-commit.sample +46 -0
  21. data/levels/blame/.githug/hooks/pre-rebase.sample +169 -0
  22. data/levels/blame/.githug/hooks/prepare-commit-msg.sample +36 -0
  23. data/levels/blame/.githug/hooks/update.sample +128 -0
  24. data/levels/blame/.githug/index +0 -0
  25. data/levels/blame/.githug/info/exclude +6 -0
  26. data/levels/blame/.githug/logs/HEAD +5 -0
  27. data/levels/blame/.githug/logs/refs/heads/master +5 -0
  28. data/levels/blame/.githug/objects/00/d6bf5341b263ccaf32e7973be55126eb30a343 +0 -0
  29. data/levels/blame/.githug/objects/05/07c26fed4d111a8344763be9af68af90f0ecf2 +0 -0
  30. data/levels/blame/.githug/objects/09/4094808dc6dc336c93c8602190a9e5f7bd6a11 +2 -0
  31. data/levels/blame/.githug/objects/21/15d78864000292628872941b14521f90187eed +0 -0
  32. data/levels/blame/.githug/objects/31/11dda1f5b08d50ac44b99acabfa54f1e6e72b0 +2 -0
  33. data/levels/blame/.githug/objects/50/8db115ba34a0e4e8667653aebe0265bb4f7e80 +0 -0
  34. data/levels/blame/.githug/objects/5e/8863df752e3b7f2150df7c78f12bef6f1ff00e +0 -0
  35. data/levels/blame/.githug/objects/67/788a4b90180c7588d7bd0ad8032957b0f429ba +0 -0
  36. data/levels/blame/.githug/objects/70/d00535a3a25b0ac1736dd3d306d6271e5427ed +0 -0
  37. data/levels/blame/.githug/objects/97/bdd0cccf9f4b8730f78cb53a81a74f205dbcc2 +1 -0
  38. data/levels/blame/.githug/objects/ab/08819ba3ffaeba17d4f870dc3a458a904519f4 +0 -0
  39. data/levels/blame/.githug/objects/be/96fe46de646f6a5c728f90cc884aef96fa1d6f +0 -0
  40. data/levels/blame/.githug/objects/cd/9c6b9ab1a6f56cccc69b6aa661f1d67ba5fb46 +0 -0
  41. data/levels/blame/.githug/objects/dd/df1d8ebd60eec169c15a5b23cb49a58d2ed5a0 +4 -0
  42. data/levels/blame/.githug/objects/ff/d39c2dbfd94bdbca06d48686e0cbda642f3de7 +1 -0
  43. data/levels/blame/.githug/refs/heads/master +1 -0
  44. data/levels/blame/config.rb +16 -0
  45. data/levels/clone.rb +10 -0
  46. data/levels/clone_to_folder.rb +10 -0
  47. data/levels/commit.rb +17 -0
  48. data/levels/config.rb +28 -0
  49. data/levels/contribute.rb +25 -0
  50. data/levels/diff.rb +16 -0
  51. data/levels/diff/.githug/COMMIT_EDITMSG +1 -0
  52. data/levels/diff/.githug/HEAD +1 -0
  53. data/levels/diff/.githug/config +5 -0
  54. data/levels/diff/.githug/description +1 -0
  55. data/levels/diff/.githug/hooks/applypatch-msg.sample +15 -0
  56. data/levels/diff/.githug/hooks/commit-msg.sample +24 -0
  57. data/levels/diff/.githug/hooks/post-commit.sample +8 -0
  58. data/levels/diff/.githug/hooks/post-receive.sample +15 -0
  59. data/levels/diff/.githug/hooks/post-update.sample +8 -0
  60. data/levels/diff/.githug/hooks/pre-applypatch.sample +14 -0
  61. data/levels/diff/.githug/hooks/pre-commit.sample +46 -0
  62. data/levels/diff/.githug/hooks/pre-rebase.sample +169 -0
  63. data/levels/diff/.githug/hooks/prepare-commit-msg.sample +36 -0
  64. data/levels/diff/.githug/hooks/update.sample +128 -0
  65. data/levels/diff/.githug/index +0 -0
  66. data/levels/diff/.githug/info/exclude +6 -0
  67. data/levels/diff/.githug/logs/HEAD +1 -0
  68. data/levels/diff/.githug/logs/refs/heads/master +1 -0
  69. data/levels/diff/.githug/objects/1b/6582364621c92707b587409cedbc4f77fc0cee +0 -0
  70. data/levels/diff/.githug/objects/4f/703ca9bd25781b6758eeb3c42ed5348610ba6d +2 -0
  71. data/levels/diff/.githug/objects/dc/aa55e97af34402e84d5336da37abcccc23cba6 +3 -0
  72. data/levels/diff/.githug/refs/heads/master +1 -0
  73. data/levels/diff/app.rb +42 -0
  74. data/levels/init.rb +10 -0
  75. data/levels/status.rb +26 -0
  76. data/lib/githug.rb +11 -0
  77. data/lib/githug/cli.rb +68 -0
  78. data/lib/githug/game.rb +40 -0
  79. data/lib/githug/level.rb +83 -0
  80. data/lib/githug/profile.rb +41 -0
  81. data/lib/githug/repository.rb +42 -0
  82. data/lib/githug/ui.rb +73 -0
  83. data/lib/githug/version.rb +3 -0
  84. data/spec/githug/cli_spec.rb +80 -0
  85. data/spec/githug/game_spec.rb +56 -0
  86. data/spec/githug/level_spec.rb +131 -0
  87. data/spec/githug/profile_spec.rb +36 -0
  88. data/spec/githug/repository_spec.rb +98 -0
  89. data/spec/githug/ui_spec.rb +84 -0
  90. data/spec/spec_helper.rb +1 -0
  91. metadata +178 -0
@@ -0,0 +1,10 @@
1
+ difficulty 1
2
+ description "Initialize an empty repository"
3
+
4
+ solution do
5
+ repo.valid?
6
+ end
7
+
8
+ hint do
9
+ puts "You can type `git` in your shell to get a list of available git commands"
10
+ end
@@ -0,0 +1,26 @@
1
+ difficulty 1
2
+ description "There are some files in this repository, one of the files is untracked, which file is it?"
3
+
4
+ setup do
5
+ repo.init
6
+ %w{config.rb README setup.rb deploy.rb Guardfile}.each do |file|
7
+ FileUtils.touch(file)
8
+ repo.add(file)
9
+ end
10
+ FileUtils.touch("database.yml")
11
+ end
12
+
13
+ solution do
14
+
15
+ name = request("What is the full file name of the untracked file?")
16
+
17
+ if name != "database.yml"
18
+ return false
19
+ end
20
+
21
+ true
22
+ end
23
+
24
+ hint do
25
+ puts "You are looking for a command to identify the status of the repository."
26
+ end
@@ -0,0 +1,11 @@
1
+ require 'grit'
2
+ require "githug/version"
3
+
4
+ require 'githug/ui'
5
+ require 'githug/game'
6
+ require 'githug/profile'
7
+ require 'githug/level'
8
+ require 'githug/repository'
9
+
10
+ Githug::UI.in_stream = STDIN
11
+ Githug::UI.out_stream = STDOUT
@@ -0,0 +1,68 @@
1
+ require 'thor'
2
+ require 'githug'
3
+ module Githug
4
+ class CLI < Thor
5
+
6
+
7
+ default_task :play
8
+
9
+ desc :play, "Initialize the game"
10
+
11
+ def play
12
+ UI.word_box("Githug")
13
+ make_directory
14
+ game = Game.new
15
+ game.play_level
16
+ end
17
+
18
+ desc :hint, "Get a hint for the current level"
19
+
20
+ def hint
21
+ if level = load_level
22
+ level.show_hint
23
+ end
24
+ end
25
+
26
+ desc :reset, "Reset the current level"
27
+
28
+ def reset
29
+ if level = load_level
30
+ UI.word_box("Githug")
31
+ UI.puts("resetting level")
32
+ level.setup_level
33
+ level.full_description
34
+ end
35
+ end
36
+
37
+ no_tasks do
38
+
39
+ def load_level
40
+ profile = Profile.load
41
+ Level.load(profile.level)
42
+ end
43
+
44
+
45
+ def make_directory
46
+ if File.exists?("./git_hug")
47
+ UI.puts "Please change into the git_hug directory"
48
+ exit
49
+ end
50
+
51
+ unless File.basename(Dir.pwd) == "git_hug"
52
+ if UI.ask("No githug directory found, do you wish to create one?")
53
+ Dir.mkdir("./git_hug")
54
+ Dir.chdir("git_hug")
55
+ File.open(".gitignore", "w") do |file|
56
+ file.write(".profile.yml")
57
+ end
58
+ else
59
+ UI.puts("Exiting")
60
+ exit
61
+ end
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,40 @@
1
+ module Githug
2
+ class Game
3
+
4
+ attr_accessor :profile
5
+
6
+ def initialize
7
+ @profile = Profile.load
8
+ end
9
+
10
+ def play_level
11
+ solve = true
12
+ if profile.level == 0
13
+ UI.puts("Welcome to Githug")
14
+ solve = false
15
+ level_bump
16
+ else
17
+ level = Level.load(profile.level)
18
+ if solve && level
19
+ if level.solve
20
+ UI.success "Congratulations, you have solved the level"
21
+ level_bump
22
+ else
23
+ UI.error "Sorry, this solution is not quite right!"
24
+ UI.puts level.full_description
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def level_bump
31
+ profile.level += 1
32
+ profile.save
33
+ if level = Level.load(profile.level)
34
+ UI.puts(level.full_description)
35
+ level.setup_level
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,83 @@
1
+ module Githug
2
+ class Level
3
+ include UI
4
+
5
+ LEVELS = [nil, "init", "add", "commit", "config", "clone", "clone_to_folder", "status", "diff", "blame", "contribute"]
6
+
7
+ attr_accessor :level_no, :level_path
8
+
9
+ class << self
10
+
11
+ def load(level_no)
12
+ level = new
13
+ level_path = "#{File.dirname(__FILE__)}/../../levels/#{LEVELS[level_no]}"
14
+ location = "#{level_path}.rb"
15
+ return false unless File.exists?(location)
16
+ level.instance_eval(File.read(location))
17
+ level.level_no = level_no
18
+ level.level_path = level_path
19
+ level
20
+ end
21
+
22
+ end
23
+
24
+ def init_from_level
25
+ FileUtils.cp_r("#{level_path}/.", ".")
26
+ FileUtils.mv(".githug", ".git")
27
+ end
28
+
29
+ def difficulty(num)
30
+ @difficulty = num
31
+ end
32
+
33
+ def description(description)
34
+ @description = description
35
+ end
36
+
37
+ def solution(&block)
38
+ @solution = block
39
+ end
40
+
41
+ def setup(&block)
42
+ @setup = block
43
+ end
44
+
45
+ def hint(&hint)
46
+ @hint = hint
47
+ end
48
+
49
+ def full_description
50
+ UI.puts
51
+ UI.puts "Level: #{level_no}"
52
+ UI.puts "Difficulty: #{"*"*@difficulty}"
53
+ UI.puts
54
+ UI.puts @description
55
+ UI.puts
56
+ end
57
+
58
+ def setup_level
59
+ repo.reset
60
+ @setup.call if @setup
61
+ end
62
+
63
+ def repo(location = "")
64
+ @repo ||= Repository.new(location)
65
+ end
66
+
67
+ def solve
68
+ @solution.call
69
+ rescue
70
+ false
71
+ end
72
+
73
+
74
+ def show_hint
75
+ UI.word_box("Githug")
76
+ if @hint
77
+ @hint.call
78
+ else
79
+ UI.puts("No hints available for this level")
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,41 @@
1
+ require 'yaml'
2
+ module Githug
3
+ class Profile
4
+ PROFILE_FILE = ".profile.yml"
5
+
6
+ attr_accessor :settings
7
+
8
+ class << self
9
+ def load
10
+ settings = {
11
+ :level => 0
12
+ }
13
+
14
+ settings.merge! YAML::load(File.open(PROFILE_FILE)) if File.exists?(PROFILE_FILE)
15
+ self.new(settings)
16
+ end
17
+ end
18
+
19
+
20
+ def method_missing(method, *args, &block)
21
+ if method.to_s.end_with?("=")
22
+ method = method.to_s.chop.to_sym
23
+ return settings[method] = args[0] if settings.include?(method)
24
+ end
25
+ return(settings[method]) if settings.include?(method)
26
+ super
27
+ end
28
+
29
+ def initialize(settings)
30
+ @settings = settings
31
+ end
32
+
33
+ def save
34
+ File.open(PROFILE_FILE, 'w') do |out|
35
+ YAML.dump(settings, out)
36
+ end
37
+ end
38
+
39
+
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ module Githug
2
+ class Repository
3
+
4
+ attr_accessor :grit
5
+
6
+ def initialize(location = ".")
7
+ @grit = Grit::Repo.new(location)
8
+ rescue Grit::InvalidGitRepositoryError
9
+ @grit = nil
10
+ end
11
+
12
+ def reset
13
+ dont_delete = ["..", ".", ".gitignore", ".profile.yml"]
14
+ if File.basename(Dir.pwd) == "git_hug"
15
+ Dir.entries(Dir.pwd).each do |file|
16
+ FileUtils.rm_rf(file) unless dont_delete.include?(file)
17
+ end
18
+ end
19
+ end
20
+
21
+ def valid?
22
+ !@grit.nil?
23
+ end
24
+
25
+ def init(gitignore = true)
26
+ @grit = Grit::Repo.init(".")
27
+ if gitignore
28
+ @grit.add(".gitignore")
29
+ @grit.commit("added .gitignore")
30
+ end
31
+ end
32
+
33
+ def method_missing(method, *args, &block)
34
+ if @grit && @grit.respond_to?(method)
35
+ return @grit.send(method, *args, &block)
36
+ end
37
+ super
38
+ end
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,73 @@
1
+ module Githug
2
+ module UI
3
+
4
+ @@out_stream
5
+ @@in_stream
6
+
7
+ class << self
8
+
9
+ def out_stream=(out)
10
+ @@out_stream = out
11
+ end
12
+
13
+ def in_stream=(in_stream)
14
+ @@in_stream = in_stream
15
+ end
16
+
17
+ def puts(string = "")
18
+ @@out_stream.puts(string)
19
+ end
20
+
21
+ def print(string)
22
+ @@out_stream.print(string)
23
+ end
24
+
25
+ def gets
26
+ @@in_stream.gets
27
+ end
28
+
29
+ def line
30
+ puts("*"*80)
31
+ end
32
+
33
+ def word_box(string)
34
+ space_length = (80/2) - ((string.length/2)+1)
35
+ line
36
+ print "*"
37
+ print " "*space_length
38
+ print string
39
+ print " "*space_length
40
+ puts "*"
41
+ line
42
+ end
43
+
44
+ def request(msg)
45
+ print("#{msg} ")
46
+ gets.chomp
47
+ end
48
+
49
+ def ask(msg)
50
+ request("#{msg} [yn] ") == 'y'
51
+ end
52
+
53
+ def colorize(text, color_code)
54
+ puts "#{color_code}#{text}\033[0m"
55
+ end
56
+
57
+ def error(text)
58
+ colorize(text, "\033[31m")
59
+ end
60
+
61
+ def success(text)
62
+ colorize(text, "\033[32m")
63
+ end
64
+
65
+ end
66
+
67
+ def method_missing(method, *args, &block)
68
+ return UI.send(method, *args) if UI.methods(false).include?(method)
69
+ super
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module Githug
2
+ VERSION = "0.0.9"
3
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+ require 'githug/cli'
3
+
4
+ describe Githug::CLI do
5
+
6
+ before(:each) do
7
+ game = mock.as_null_object
8
+ @cli = Githug::CLI.new
9
+ Githug::Game.stub(:new).and_return(game)
10
+ end
11
+
12
+ it "should print the logo" do
13
+ Githug::UI.should_receive(:word_box).with("Githug")
14
+ @cli.stub(:make_directory)
15
+ @cli.play
16
+ end
17
+
18
+ it "should create a directory if one does not exist" do
19
+ Githug::UI.stub(:ask).and_return(true)
20
+ Dir.should_receive(:mkdir).with("./git_hug")
21
+ Dir.should_receive(:chdir).with("git_hug")
22
+ File.should_receive(:open).with(".gitignore", "w").and_return(true)
23
+ @cli.make_directory
24
+ end
25
+
26
+ it "should not make a directory if you are in the game directory" do
27
+ Dir.stub(:pwd).and_return("/home/git_hug")
28
+ Githug::UI.should_not_receive(:ask)
29
+ @cli.make_directory
30
+ end
31
+
32
+ it "should exit if the user selects no" do
33
+ Githug::UI.stub(:ask).and_return(false)
34
+ lambda {@cli.make_directory}.should raise_error(SystemExit)
35
+ end
36
+
37
+ it "should prompt to change into the directory if it exists" do
38
+ File.stub(:exists?).and_return(true)
39
+ Githug::UI.should_receive(:puts).with("Please change into the git_hug directory")
40
+ lambda {@cli.make_directory}.should raise_error(SystemExit)
41
+ end
42
+
43
+ describe "level methods" do
44
+ before(:each) do
45
+ @level = mock
46
+ @profile = mock
47
+ @profile.stub(:level).and_return(1)
48
+ Githug::Profile.stub(:load).and_return(@profile)
49
+ Githug::Level.stub(:load).and_return(@level)
50
+ end
51
+
52
+ it "should call the hint method on the level" do
53
+ @level.should_receive(:show_hint)
54
+ @cli.hint
55
+ end
56
+
57
+ describe "reset" do
58
+
59
+
60
+ it "should reset the current level" do
61
+ @level.should_receive(:setup_level)
62
+ @level.should_receive(:full_description)
63
+ Githug::UI.should_receive(:word_box).with("Githug")
64
+ Githug::UI.should_receive(:puts).with("resetting level")
65
+ @cli.reset
66
+ end
67
+
68
+ it "should not reset if the level cannot be loaded" do
69
+ Githug::Level.stub(:load).and_return(false)
70
+ @level.should_not_receive(:setup_level)
71
+ @level.should_not_receive(:full_description)
72
+ Githug::UI.should_not_receive(:word_box).with("Githug")
73
+ Githug::UI.should_not_receive(:puts).with("resetting level")
74
+ @cli.reset
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end