twit 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 289a3be1ed0e67bea59cffdce6e82f2802511b2c
4
+ data.tar.gz: 7690c43ff2be9ab8f81a26757f754162b4f57818
5
+ SHA512:
6
+ metadata.gz: bcbd3f91dd0a59ea2c4162b0449ea8b999e2d45e05105cc11c9fd6a71ddba3775da26ff7f901805d1f1af8a7a614e4f8e680c643476dfd1302807982c102bf0b
7
+ data.tar.gz: 7a2097cad0b49b9c9a312433dfe344b5ad4ce5f2c29d18e53a31cc41adaa6c4493417565cbf890a62575d6a40f74c468123db3b99d01d35d55d55e3d59371112
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ bin
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in twit.gemspec
4
+ gemspec
@@ -0,0 +1,69 @@
1
+ # Twit: simplified git wrapper
2
+
3
+ ## UI
4
+
5
+ ### Local
6
+
7
+ twit init
8
+
9
+ git init
10
+
11
+ twit list
12
+
13
+ git branch
14
+
15
+ twit new <branch>
16
+
17
+ git checkout -b <branch>
18
+
19
+ twit save <message>
20
+
21
+ git add --all && git commit -m <message>
22
+
23
+ twit saveas <branch>
24
+
25
+ git checkout -b <branch> && git add --all && git commit -m "New branch: <branch>"
26
+
27
+ twit overwrite <branch>
28
+
29
+ PATCH="$(mktemp /tmp/patchXXXXXX)"
30
+ git add --all && git diff --cached <branch> > $PATCH && git reset --hard && git checkout <branch> && git apply "${PATCH}" && rm "${PATCH}" && git add --all && git commit -m "Overwrite <branch>"
31
+
32
+ twit open <branch>
33
+
34
+ git checkout <branch>
35
+
36
+ twit delete <branch>
37
+
38
+ git branch -d <branch>
39
+
40
+ twit discard
41
+
42
+ git reset --hard HEAD
43
+
44
+ twit history
45
+
46
+ git log --pretty=format:'%C(yellow)%h %Cred%ad%Cblue%d %Creset%s %Cgreen[%an]' --date=relative --graph --branches
47
+
48
+ twit merge <from-branch>
49
+
50
+ git merge --no-ff <from-branch>
51
+
52
+ ### Remote
53
+
54
+ twit connect <url>
55
+
56
+ git remote add origin <url>
57
+
58
+ twit sync <branch>
59
+
60
+ git pull --rebase origin <branch> && git push origin <branch>
61
+
62
+ twit publish <tag> <message>
63
+
64
+ git tag -a <tag> <message> && git push origin tag
65
+
66
+ ## Impl
67
+
68
+ - Ruby
69
+ - Thor
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ben Pringle
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,66 @@
1
+ # Twit: simplified git wrapper
2
+
3
+ Twit makes [git](http://git-scm.com) easier for beginners.
4
+
5
+ ## Installation
6
+
7
+ To install, simply run:
8
+
9
+ gem install twit
10
+
11
+ (On some systems, this may require `sudo`.)
12
+
13
+ ## Usage
14
+
15
+ ### `init` -- create a new repository
16
+
17
+ twit init
18
+
19
+ Initialize a new git repository in the current directory.
20
+
21
+ ### `save` -- take a snapshot of all files
22
+
23
+ twit save <DESCRIBE_CHANGES>
24
+
25
+ Take a snapshot of all files in the directory.
26
+
27
+ Any changes on the working tree will be committed to the current branch.
28
+
29
+ ## API
30
+
31
+ All command-line functions are available for use as a Ruby library as well.
32
+
33
+ require 'twit'
34
+
35
+ # Create a new repository
36
+ repo = Twit.init
37
+
38
+ # Make some changes to the directory
39
+ File.open('foo', 'w') { |f| f.write('bar\n') }
40
+
41
+ # Take a snapshot
42
+ Twit.save "Add some foo"
43
+
44
+ ## Development
45
+
46
+ ### Setup
47
+
48
+ Clone the repository.
49
+
50
+ Install dependencies with:
51
+
52
+ bundle install --binstubs
53
+
54
+ ### Testing
55
+
56
+ Run the tests with:
57
+
58
+ bin/rspec
59
+
60
+ ### Documentation
61
+
62
+ Generate the docs with
63
+
64
+ bin/yard
65
+
66
+ They will appear in the `./doc` folder.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'twit/cli'
3
+ Twit::CLI.start(ARGV)
@@ -0,0 +1,15 @@
1
+ require "twit/version"
2
+ require "twit/repo"
3
+ require "twit/init"
4
+ require "twit/error"
5
+
6
+ # This module exposes twit commands as methods.
7
+ module Twit
8
+
9
+ # Get a {Twit::Repo} representing the repository for the current working
10
+ # directory.
11
+ def self.repo
12
+ Twit::Repo.new
13
+ end
14
+
15
+ end
@@ -0,0 +1,31 @@
1
+ require 'thor'
2
+ require 'twit'
3
+
4
+ module Twit
5
+
6
+ # Automatically-built command-line interface (using Thor).
7
+ class CLI < Thor
8
+
9
+ desc "init", "Create an empty repository in the current directory"
10
+ # Pass method to Twit module
11
+ def init
12
+ Twit.init
13
+ end
14
+
15
+ desc "save <DESCRIBE_CHANGES>", "Take a snapshot of all files"
16
+ # Pass method to default repo
17
+ def save message = nil
18
+ if message.nil?
19
+ $stderr.puts "Please supply a message describing your changes.\n e.g. twit save \"Update the README\""
20
+ exit false
21
+ end
22
+ begin
23
+ Twit.repo.save message
24
+ rescue NothingToCommitError
25
+ puts "No new edits to save"
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,13 @@
1
+ module Twit
2
+
3
+ # A generic error raised by Twit. (All other errors inherit from this one.)
4
+ class Error < RuntimeError; end
5
+
6
+ # Raised when commands are executed in a directory that is not part of a git
7
+ # repository.
8
+ class NotARepositoryError < Error; end
9
+
10
+ # Raised when trying to commit nothing.
11
+ class NothingToCommitError < Error; end
12
+
13
+ end
@@ -0,0 +1,21 @@
1
+ require 'open3'
2
+ require 'twit/error'
3
+
4
+ module Twit
5
+
6
+ # Initialize a git repository in a directory. Return a Twit::Repo object
7
+ # representing the new repository.
8
+ #
9
+ # If no argument is supplied, use the working directory.
10
+ def self.init dir = nil
11
+ dir ||= Dir.getwd
12
+ Dir.chdir dir do
13
+ stdout, stderr, status = Open3.capture3 "git init"
14
+ if status != 0
15
+ raise Error, stderr
16
+ end
17
+ end
18
+ Repo.new dir
19
+ end
20
+
21
+ end
@@ -0,0 +1,35 @@
1
+ require 'open3'
2
+ require 'twit/error'
3
+ require 'twit/repo/save'
4
+
5
+ module Twit
6
+
7
+ # An object to represent a git repository.
8
+ class Repo
9
+
10
+ # The root directory of the repository.
11
+ attr_reader :root
12
+
13
+ # Takes an optional argument of a Dir object to treat as the repository
14
+ # root. If not, try to detect the root of the current repository.
15
+ #
16
+ # When run without arguments in a directory not part of a git repository,
17
+ # raise {Twit::NotARepositoryError}.
18
+ def initialize root = nil
19
+ if root.nil?
20
+ stdout, stderr, status = Open3.capture3 "git rev-parse --show-toplevel"
21
+ if status != 0
22
+ case stderr
23
+ when /Not a git repository/
24
+ raise NotARepositoryError
25
+ else
26
+ raise Error, stderr
27
+ end
28
+ end
29
+ root = stdout.strip
30
+ end
31
+ @root = root
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,23 @@
1
+ require 'open3'
2
+ require 'twit/error'
3
+
4
+ module Twit
5
+ class Repo
6
+
7
+ # Update the snapshot of the current directory.
8
+ def save message
9
+ Dir.chdir @root do
10
+ cmd = "git add --all && git commit -m \"#{message}\""
11
+ stdout, stderr, status = Open3.capture3 cmd
12
+ if status != 0
13
+ if /nothing to commit/.match stdout
14
+ raise NothingToCommitError
15
+ else
16
+ raise Error, stderr
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ module Twit
2
+ # Gem version
3
+ VERSION = "0.0.1"
4
+ end
@@ -0,0 +1,39 @@
1
+ require "twit/cli"
2
+
3
+ describe Twit::CLI do
4
+
5
+ before do
6
+ @cli = Twit::CLI.new
7
+
8
+ # Mock out Twit library to avoid accidentally clobbering anything during
9
+ # testing.
10
+ stub_const("Twit", double('Twit'))
11
+ end
12
+
13
+ describe "init" do
14
+ it "calls Twit.init" do
15
+ Twit.should_receive(:init)
16
+ @cli.invoke :init
17
+ end
18
+ end
19
+
20
+ describe "save" do
21
+ it "calls Twit.repo.save" do
22
+ message = "my test commit message"
23
+ repo = double('repo')
24
+
25
+ # Expected call is `Twit.repo.save message`
26
+ repo.should_receive(:save).with(message)
27
+ Twit.should_receive(:repo).and_return(repo)
28
+
29
+ @cli.invoke :save, [message]
30
+ end
31
+ it "asks for commit message" do
32
+ $stderr.should_receive(:puts).with /message/
33
+ expect {
34
+ @cli.invoke :save
35
+ }.to raise_error SystemExit
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,43 @@
1
+ require 'tmpdir'
2
+
3
+ require 'twit/init'
4
+ require 'twit/repo'
5
+
6
+ describe Twit do
7
+ describe "::init" do
8
+
9
+ before do
10
+ @tmpdir = Dir.mktmpdir
11
+ end
12
+
13
+ after do
14
+ FileUtils.remove_entry @tmpdir
15
+ end
16
+
17
+ # Check if the current working directory is a git repository.
18
+ def expect_cwd_to_be_repo
19
+ `git status`
20
+ expect($?.exitstatus).to eq(0)
21
+ end
22
+
23
+ it "initializes given directory" do
24
+ Twit.init @tmpdir
25
+ Dir.chdir @tmpdir do
26
+ expect_cwd_to_be_repo
27
+ end
28
+ end
29
+
30
+ it "initializes the working directory by default" do
31
+ Dir.chdir @tmpdir do
32
+ Twit.init
33
+ expect_cwd_to_be_repo
34
+ end
35
+ end
36
+
37
+ it "returns a repo object" do
38
+ repo = Twit.init @tmpdir
39
+ expect(repo).to be_instance_of(Twit::Repo)
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ require 'tmpdir'
2
+ require 'securerandom'
3
+
4
+ require 'twit/repo'
5
+ require 'twit/error'
6
+
7
+ describe Twit::Repo, "#save" do
8
+
9
+ before do
10
+ @tmpdir = Dir.mktmpdir
11
+ @repo = Twit.init @tmpdir
12
+ @oldwd = Dir.getwd
13
+ Dir.chdir @tmpdir
14
+ end
15
+
16
+ after do
17
+ Dir.chdir @oldwd
18
+ FileUtils.remove_entry @tmpdir
19
+ end
20
+
21
+ context "files in working tree" do
22
+ before do
23
+ 3.times do |i|
24
+ File.open("file#{i}.txt", 'w') { |f| f.write("file#{i} contents\n") }
25
+ end
26
+ end
27
+ it "commits the entire working tree" do
28
+ @repo.save "created three files"
29
+ expect(`git status`).to include('working directory clean')
30
+ end
31
+ it "makes a commit" do
32
+ msg = "commit msg #{SecureRandom.hex(4)}"
33
+ @repo.save msg
34
+ expect(`git log`).to include(msg)
35
+ end
36
+ end
37
+
38
+ it "raises error in new repository" do
39
+ expect {
40
+ @repo.save "trying to save"
41
+ }.to raise_error(Twit::NothingToCommitError)
42
+ end
43
+
44
+ it "raises error with nothing to commit" do
45
+ # First, make sure there's at least one commit on the log.
46
+ File.open("foo", 'w') { |f| f.write("bar\n") }
47
+ `git add foo && git commit -m "add foo"`
48
+
49
+ # Now there should be nothing more to commit
50
+ expect {
51
+ @repo.save "trying to save"
52
+ }.to raise_error(Twit::NothingToCommitError)
53
+ end
54
+
55
+ end
@@ -0,0 +1,61 @@
1
+ require 'tmpdir'
2
+ require 'tempfile'
3
+
4
+ require 'twit/repo'
5
+ require 'twit/error'
6
+
7
+ describe Twit::Repo do
8
+ describe "#new" do
9
+
10
+ before do
11
+ @tmpdir = Dir.mktmpdir
12
+
13
+ # OS X uses /private/tmp and /tmp interchangably, so straight comparison
14
+ # of directories sometimes fails. Instead, detect this particular
15
+ # directory by creating a file in an end checking for its existence.
16
+ @file_in_dir = Tempfile.new '.detect', @tmpdir
17
+ end
18
+
19
+ def expect_root dir
20
+ path = Pathname.new File.join(dir, File.basename(@file_in_dir))
21
+ expect(path).to be_exist
22
+ end
23
+
24
+ after do
25
+ FileUtils.remove_entry @tmpdir
26
+ end
27
+
28
+ it "works with a directory argument" do
29
+ repo = Twit::Repo.new @tmpdir
30
+ expect_root repo.root
31
+ end
32
+
33
+ it "detects git root while at root (no args)" do
34
+ Dir.chdir @tmpdir do
35
+ `git init`
36
+ repo = Twit::Repo.new
37
+ expect_root repo.root
38
+ end
39
+ end
40
+
41
+ it "detects git root while in subdirectory (no args)" do
42
+ Dir.chdir @tmpdir do
43
+ `git init`
44
+ Dir.mkdir 'subdir'
45
+ Dir.chdir 'subdir' do
46
+ repo = Twit::Repo.new
47
+ expect_root repo.root
48
+ end
49
+ end
50
+ end
51
+
52
+ it "raises an error when not in a repo (no args)" do
53
+ Dir.chdir @tmpdir do
54
+ expect {
55
+ repo = Twit::Repo.new
56
+ }.to raise_error Twit::NotARepositoryError
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ require "twit"
2
+
3
+ describe Twit do
4
+
5
+ describe "::repo" do
6
+ it "returns a repo object" do
7
+ repo = Twit.repo
8
+ expect(repo).to be_instance_of(Twit::Repo)
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'twit/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "twit"
8
+ spec.version = Twit::VERSION
9
+ spec.authors = ["Ben Pringle"]
10
+ spec.email = ["ben.pringle@gmail.com"]
11
+ spec.description = %q{Create a simpler abstraction over the git command}
12
+ spec.summary = %q{Simplified git wrapper}
13
+ spec.homepage = "https://github.com/Pringley/twit"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "thor"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "yard"
28
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: twit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Pringle
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2013-08-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Create a simpler abstraction over the git command
84
+ email:
85
+ - ben.pringle@gmail.com
86
+ executables:
87
+ - twit
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - .rspec
93
+ - Gemfile
94
+ - IDEAS.txt
95
+ - LICENSE.txt
96
+ - README.markdown
97
+ - Rakefile
98
+ - exe/twit
99
+ - lib/twit.rb
100
+ - lib/twit/cli.rb
101
+ - lib/twit/error.rb
102
+ - lib/twit/init.rb
103
+ - lib/twit/repo.rb
104
+ - lib/twit/repo/save.rb
105
+ - lib/twit/version.rb
106
+ - spec/twit/cli_spec.rb
107
+ - spec/twit/init_spec.rb
108
+ - spec/twit/repo/save_spec.rb
109
+ - spec/twit/repo_spec.rb
110
+ - spec/twit_spec.rb
111
+ - twit.gemspec
112
+ homepage: https://github.com/Pringley/twit
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.0.2
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Simplified git wrapper
136
+ test_files:
137
+ - spec/twit/cli_spec.rb
138
+ - spec/twit/init_spec.rb
139
+ - spec/twit/repo/save_spec.rb
140
+ - spec/twit/repo_spec.rb
141
+ - spec/twit_spec.rb
142
+ has_rdoc: