mercurial-ruby 0.7.0 → 0.7.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.
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem "open4", "~>1.3.0"
4
+
3
5
  group :development do
4
6
  gem "minitest", ">= 0"
5
7
  gem "bundler", "~> 1.0.0"
data/Gemfile.lock CHANGED
@@ -11,6 +11,7 @@ GEM
11
11
  rbx-require-relative (> 0.0.4)
12
12
  minitest (2.3.1)
13
13
  mocha (0.9.12)
14
+ open4 (1.3.0)
14
15
  rake (0.9.2)
15
16
  rbx-require-relative (0.0.5)
16
17
  rcov (0.9.9)
@@ -28,5 +29,6 @@ DEPENDENCIES
28
29
  jeweler (~> 1.6.4)
29
30
  minitest
30
31
  mocha (~> 0.9)
32
+ open4 (~> 1.3.0)
31
33
  rcov
32
34
  ruby-debug (~> 0.10)
data/README.rdoc CHANGED
@@ -52,14 +52,21 @@ See Features section below for a full list of entities and their methods.
52
52
 
53
53
  === Mercurial Entities
54
54
 
55
+ * {Mercurial::Repository Repository}
56
+ * {Mercurial::ConfigFile .hgrc} — hooks and various settings
55
57
  * {Mercurial::Commit Commits}
56
58
  * {Mercurial::Node Nodes} — files and directories
57
59
  * {Mercurial::Branch Branches}
58
60
  * {Mercurial::Tag Tags}
59
61
  * {Mercurial::Diff Diffs}
62
+ * {Mercurial::Blame Blame}
60
63
  * {Mercurial::Manifest Manifest}
61
64
  * {Mercurial::FileIndex File Index}
62
- * {Mercurial::ConfigFile Repository config} — hooks and various settings
65
+
66
+ === Custom Commands
67
+
68
+ You can use {Mercurial::Shell Shell} class to execute custom shell commands that
69
+ weren't added to the gem as first-class citizens yet.
63
70
 
64
71
  === Built-in Caching
65
72
 
@@ -77,6 +84,12 @@ Here's how you configure it:
77
84
  The gem is using a single method of the CacheStore called +fetch+.
78
85
  Cache expires automatically when repository's mtime changes, and it's your job to update it.
79
86
 
87
+ === Built-in Timeouts
88
+
89
+ You can provide a timeout for pretty much any command you are running. Do it like this:
90
+
91
+ repository.commits.all(:timeout => 5)
92
+
80
93
  == Contributing to mercurial-ruby
81
94
 
82
95
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.7.1
@@ -4,7 +4,7 @@
4
4
  #
5
5
  module Mercurial
6
6
 
7
- VERSION = '0.7.0'
7
+ VERSION = '0.7.1'
8
8
 
9
9
  class Error < RuntimeError; end
10
10
 
@@ -1,5 +1,12 @@
1
1
  module Mercurial
2
2
 
3
+ #
4
+ # The class represents Mercurial blame output. Obtained by running an +hg blame+ command.
5
+ #
6
+ # This is for the Blame object itself, {Mercurial::BlameFactory BlameFactory} is responsible
7
+ # for assembling instances of the Blame. For the list of all possible blame-related operations please
8
+ # look documentation for {Mercurial::BlameFactory BlameFactory}.
9
+ #
3
10
  class Blame
4
11
 
5
12
  attr_reader :repository
@@ -9,7 +16,10 @@ module Mercurial
9
16
  @repository = repository
10
17
  @contents = data
11
18
  end
12
-
19
+
20
+ #
21
+ # Returns an array of {Mercurial::BlameLine BlameLine} instances.
22
+ #
13
23
  def lines
14
24
  [].tap do |result|
15
25
  contents.each do |line|
@@ -1,10 +1,20 @@
1
1
  module Mercurial
2
-
2
+
3
+ #
4
+ # The class represents a single line of the Mercurial blame output.
5
+ #
3
6
  class BlameLine
4
7
 
8
+ # Commit author.
5
9
  attr_reader :author
10
+
11
+ # Line number.
6
12
  attr_reader :num
13
+
14
+ # ID of the commit associated with the line.
7
15
  attr_reader :revision
16
+
17
+ # Contents of the line.
8
18
  attr_reader :contents
9
19
 
10
20
  def initialize(attrs={})
@@ -1,9 +1,14 @@
1
1
  require 'timeout'
2
2
  require 'digest/md5'
3
+ require 'open4'
3
4
 
4
5
  module Mercurial
5
6
  class CommandError < Error; end
6
7
 
8
+ #
9
+ # This class represents a command that will be executed in a shell. You probably don't want to deal with this yourself,
10
+ # use the {Mercurial::Shell Shell} class instead.
11
+ #
7
12
  class Command
8
13
  attr_accessor :command, :repository, :use_cache, :timeout
9
14
 
@@ -47,8 +52,8 @@ module Mercurial
47
52
  def execution_proc
48
53
  Proc.new do
49
54
  debug(command)
50
- result, error = '', ''
51
- Open3.popen3(command) do |_, stdout, stderr|
55
+ result, error, = '', ''
56
+ status = Open4.popen4(command) do |pid, stdin, stdout, stderr|
52
57
  Timeout.timeout(timeout) do
53
58
  while tmp = stdout.read(102400)
54
59
  result += tmp
@@ -59,12 +64,13 @@ module Mercurial
59
64
  error += tmp
60
65
  end
61
66
  end
62
- raise_error_if_needed(error)
67
+ raise_error_if_needed(status, error)
63
68
  result
64
69
  end
65
70
  end
66
71
 
67
- def raise_error_if_needed(error)
72
+ def raise_error_if_needed(status, error)
73
+ return if status.exitstatus == 0
68
74
  if error && error != ''
69
75
  raise CommandError, error
70
76
  end
@@ -77,7 +83,7 @@ module Mercurial
77
83
  def debug(msg)
78
84
  if Mercurial.configuration.debug_mode
79
85
  puts msg
80
- end
86
+ end
81
87
  end
82
88
 
83
89
  end
@@ -1,14 +1,26 @@
1
1
  module Mercurial
2
2
 
3
+ #
4
+ # This class represents a factory for {Mercurial::Blame Blame} instances.
5
+ #
3
6
  class BlameFactory
4
7
  include Mercurial::Helper
5
8
 
9
+ # Instance of a {Mercurial::Repository Repository}.
6
10
  attr_reader :repository
7
11
 
8
12
  def initialize(repository)
9
13
  @repository = repository
10
14
  end
11
-
15
+
16
+ # Finds a blame for a specified file path at a specified revision.
17
+ # Returns an instance of {Mercurial::Blame Blame}.
18
+ #
19
+ # Omit +revision+ if you want the latest blame.
20
+ #
21
+ # === Example:
22
+ # repository.blames.for_path('some-fancy-directory/all-blame-is-on-me.rb')
23
+ #
12
24
  def for_path(path, revision=nil, cmd_options={})
13
25
  revision ||= 'tip'
14
26
  build do
@@ -15,7 +15,7 @@ module Mercurial
15
15
 
16
16
  # Return an array of {Mercurial::Branch Branch} instances for all branches in the repository.
17
17
  #
18
- # == Example:
18
+ # === Example:
19
19
  # repository.branches.all
20
20
  #
21
21
  def all(cmd_options={})
@@ -26,44 +26,44 @@ module Mercurial
26
26
 
27
27
  # Run a block for every {Mercurial::Branch Branch} instance of all branches in the repository.
28
28
  #
29
- # == Example:
29
+ # === Example:
30
30
  # repository.branches.each {|commit| ... }
31
31
  #
32
- def each(&block)
33
- all.each do |branch|
32
+ def each(cmd_options={}, &block)
33
+ all(cmd_options).each do |branch|
34
34
  block.call(branch)
35
35
  end
36
36
  end
37
37
 
38
38
  # Return an array of {Mercurial::Branch Branch} instances for all active branches in the repository.
39
39
  #
40
- # == Example:
40
+ # === Example:
41
41
  # repository.branches.active
42
42
  #
43
- def active
44
- all.find_all do |b|
43
+ def active(cmd_options={})
44
+ all(cmd_options).find_all do |b|
45
45
  b.active?
46
46
  end
47
47
  end
48
48
 
49
49
  # Return an array of {Mercurial::Branch Branch} instances for all closed branches in the repository.
50
50
  #
51
- # == Example:
51
+ # === Example:
52
52
  # repository.branches.closed
53
53
  #
54
- def closed
55
- all.find_all do |b|
54
+ def closed(cmd_options={})
55
+ all(cmd_options).find_all do |b|
56
56
  b.closed?
57
57
  end
58
58
  end
59
59
 
60
60
  # Return a {Mercurial::Branch Branch} instance for a branch with a specified name.
61
61
  #
62
- # == Example:
62
+ # === Example:
63
63
  # repository.branches.by_name('branchname')
64
64
  #
65
- def by_name(name)
66
- all.find do |b|
65
+ def by_name(name, cmd_options={})
66
+ all(cmd_options).find do |b|
67
67
  b.name == name
68
68
  end
69
69
  end
@@ -71,7 +71,7 @@ module Mercurial
71
71
  # Return an array of {Mercurial::Branch Branch} instances where a specified commit exists.
72
72
  # Experimental, doesn't always return a correct list of branches.
73
73
  #
74
- # == Example:
74
+ # === Example:
75
75
  # repository.branches.for_commit('291a498f04e9')
76
76
  #
77
77
  def for_commit(hash_id, cmd_options={})
@@ -15,7 +15,7 @@ module Mercurial
15
15
 
16
16
  # Return a parent commit for this working copy.
17
17
  #
18
- # == Example:
18
+ # === Example:
19
19
  # repository.commits.parent
20
20
  #
21
21
  def parent(cmd_options={})
@@ -27,7 +27,7 @@ module Mercurial
27
27
  # Return an array of {Mercurial::Commit Commit} instances for all changesets in the repository.
28
28
  # Accept a :limit setting.
29
29
  #
30
- # == Example:
30
+ # === Example:
31
31
  # repository.commits.all
32
32
  # repository.commits.all(:limit => 15)
33
33
  #
@@ -41,18 +41,18 @@ module Mercurial
41
41
 
42
42
  # Run a block for every {Mercurial::Commit Commit} instance of all changesets in the repository.
43
43
  #
44
- # == Example:
44
+ # === Example:
45
45
  # repository.commits.each {|commit| ... }
46
46
  #
47
- def each(&block)
48
- all.each do |commit|
47
+ def each(cmd_options={}, &block)
48
+ all(cmd_options).each do |commit|
49
49
  block.call(commit)
50
50
  end
51
51
  end
52
52
 
53
53
  # Count all changesets in the repository.
54
54
  #
55
- # == Example:
55
+ # === Example:
56
56
  # repository.commits.count
57
57
  #
58
58
  def count(cmd_options={})
@@ -63,7 +63,7 @@ module Mercurial
63
63
 
64
64
  # Count changesets in the range from hash_a to hash_b in the repository.
65
65
  #
66
- # == Example:
66
+ # === Example:
67
67
  # repository.commits.count_range(hash_a, hash_b)
68
68
  #
69
69
  def count_range(hash_a, hash_b, cmd_options={})
@@ -74,7 +74,7 @@ module Mercurial
74
74
 
75
75
  # Return an array of {Mercurial::Commit Commit} instances for changesets in a specific branch.
76
76
  #
77
- # == Example:
77
+ # === Example:
78
78
  # repository.commits.by_branch('brancname')
79
79
  #
80
80
  def by_branch(branch, cmd_options={})
@@ -85,7 +85,7 @@ module Mercurial
85
85
 
86
86
  # Return an instance of {Mercurial::Commit Commit} for a changeset with a specified id.
87
87
  #
88
- # == Example:
88
+ # === Example:
89
89
  # repository.commits.by_hash_id('291a498f04e9')
90
90
  #
91
91
  def by_hash_id(hash, cmd_options={})
@@ -96,7 +96,7 @@ module Mercurial
96
96
 
97
97
  # Return an array of {Mercurial::Commit Commit} instances for changesets with specified ids.
98
98
  #
99
- # == Example:
99
+ # === Example:
100
100
  # repository.commits.by_hash_ids('291a498f04e9', '63f70b2314ed')
101
101
  #
102
102
  def by_hash_ids(*args)
@@ -117,7 +117,7 @@ module Mercurial
117
117
 
118
118
  # Return an array of {Mercurial::Commit Commit} instances for a specified range of changeset ids.
119
119
  #
120
- # == Example:
120
+ # === Example:
121
121
  # repository.commits.for_range('bf6386c0a0cc', '63f70b2314ed')
122
122
  #
123
123
  def for_range(hash_a, hash_b, options={}, cmd_options={})
@@ -129,7 +129,7 @@ module Mercurial
129
129
 
130
130
  # Return an array of {Mercurial::Commit Commit} instances that appear in hg log before the specified revision id.
131
131
  #
132
- # == Example:
132
+ # === Example:
133
133
  # repository.commits.before('bf6386c0a0cc')
134
134
  #
135
135
  def before(hash_id, options={}, cmd_options={})
@@ -138,7 +138,7 @@ module Mercurial
138
138
 
139
139
  # Return an array of {Mercurial::Commit Commit} instances that appear in hg log after the specified revision id.
140
140
  #
141
- # == Example:
141
+ # === Example:
142
142
  # repository.commits.after('bf6386c0a0cc')
143
143
  #
144
144
  def after(hash_id, options={}, cmd_options={})
@@ -147,7 +147,7 @@ module Mercurial
147
147
 
148
148
  # Return an instance of {Mercurial::Commit Commit} for a repository's tip changeset (latest).
149
149
  #
150
- # == Example:
150
+ # === Example:
151
151
  # repository.commits.tip
152
152
  #
153
153
  def tip(cmd_options={})
@@ -159,7 +159,7 @@ module Mercurial
159
159
 
160
160
  # Return an array of {Mercurial::Commit Commit} instances that appear in hg log as ancestors of the specified commit ID.
161
161
  #
162
- # == Example:
162
+ # === Example:
163
163
  # repository.commits.ancestors_of('bf6386c0a0cc')
164
164
  #
165
165
  def ancestors_of(hash_id, options={}, cmd_options={})
@@ -16,7 +16,7 @@ module Mercurial
16
16
  # Returns an array of {Mercurial::Diff Diff} instances for a specified
17
17
  # instance of {Mercurial::Commit Commit}. Represents changeset's diffs.
18
18
  #
19
- # == Example:
19
+ # === Example:
20
20
  # commit = repository.commits.by_hash_id('291a498f04e9')
21
21
  # repository.diffs.for_commit(commit)
22
22
  #
@@ -1,13 +1,23 @@
1
1
  module Mercurial
2
2
 
3
+ #
4
+ # This class is a handy way to manage hooks in your repository.
5
+ #
3
6
  class HookFactory
4
7
 
8
+ # Instance of {Mercurial::Repository Repository}.
5
9
  attr_reader :repository
6
10
 
7
11
  def initialize(repository)
8
12
  @repository = repository
9
13
  end
10
14
 
15
+ #
16
+ # Finds all repository hooks. Returns an array of {Mercurial::Hook Hook} instances.
17
+ #
18
+ # === Example:
19
+ # repository.hooks.all
20
+ #
11
21
  def all
12
22
  [].tap do |returning|
13
23
  repository.config.find_header('hooks').each_pair do |name, value|
@@ -16,18 +26,36 @@ module Mercurial
16
26
  end
17
27
  end
18
28
 
29
+ #
30
+ # Finds a specific hook by it's name. Returns an instance of {Mercurial::Hook Hook}.
31
+ #
32
+ # === Example:
33
+ # repository.hooks.by_name('changegroup')
34
+ #
19
35
  def by_name(name)
20
36
  all.find do |h|
21
37
  h.name == name.to_s
22
38
  end
23
39
  end
24
40
 
41
+ #
42
+ # Adds a new hook to the repository.
43
+ #
44
+ # === Example:
45
+ # repository.hooks.add('changegroup', 'do_something')
46
+ #
25
47
  def add(name, value)
26
48
  build(name, value).tap do |hook|
27
49
  hook.save
28
50
  end
29
51
  end
30
52
 
53
+ #
54
+ # Removes a hook from the repository.
55
+ #
56
+ # === Example:
57
+ # repository.hooks.remove('changegroup')
58
+ #
31
59
  def remove(name)
32
60
  if hook = by_name(name)
33
61
  hook.destroy!
@@ -6,7 +6,7 @@ module Mercurial
6
6
  #
7
7
  class NodeFactory
8
8
 
9
- # Instance of {Mercurial::Repository Repository}.
9
+ # Instance of a {Mercurial::Repository Repository}.
10
10
  attr_reader :repository
11
11
 
12
12
  def initialize(repository)
@@ -19,7 +19,7 @@ module Mercurial
19
19
  # Will find node in the latest version of repo if revision is ommitted.
20
20
  # Will return nil if node wasn't found.
21
21
  #
22
- # == Example:
22
+ # === Example:
23
23
  # repository.nodes.find('/')
24
24
  # repository.nodes.find('some-fancy-directory/Weird File Name.pdf', '291a498f04e9')
25
25
  # repository.nodes.find('some-fancy-directory/subdirectory/', '291a498f04e9')
@@ -58,7 +58,7 @@ module Mercurial
58
58
  #
59
59
  # Will find node in the latest version of repo if revision is ommitted.
60
60
  #
61
- # == Example:
61
+ # === Example:
62
62
  # repository.nodes.entries_for('/')
63
63
  # repository.nodes.entries_for('some-fancy-directory/subdirectory/', '291a498f04e9')
64
64
  #
@@ -15,7 +15,7 @@ module Mercurial
15
15
 
16
16
  # Return an array of {Mercurial::Tag Tag} instances for all tags in the repository.
17
17
  #
18
- # == Example:
18
+ # === Example:
19
19
  # repository.tags.all
20
20
  #
21
21
  def all(cmd_options={})
@@ -26,11 +26,11 @@ module Mercurial
26
26
 
27
27
  # Return a {Mercurial::Tag Tag} instance for a tag with a specified name.
28
28
  #
29
- # == Example:
29
+ # === Example:
30
30
  # repository.tags.by_name('tagname')
31
31
  #
32
- def by_name(name)
33
- all.find do |b|
32
+ def by_name(name, cmd_options={})
33
+ all(cmd_options).find do |b|
34
34
  b.name == name
35
35
  end
36
36
  end
@@ -2,7 +2,7 @@ module Mercurial
2
2
 
3
3
  # This class was ported from grit.
4
4
  #
5
- # This implements a file-based 'file index', an simple index of
5
+ # It implements a file-based 'file index', a simple index of
6
6
  # all of the reachable commits in a repo, along with the parents
7
7
  # and which files were modified during each commit.
8
8
  #
@@ -21,7 +21,7 @@ module Mercurial
21
21
  # Returns contents of the manifest as a String at a specified revision.
22
22
  # Latest version of the manifest is used if +revision+ is ommitted.
23
23
  #
24
- # == Example:
24
+ # === Example:
25
25
  # repository.manifest.contents
26
26
  #
27
27
  def contents(revision=nil, cmd_options={})
@@ -32,7 +32,7 @@ module Mercurial
32
32
  # Returns an array of file paths from manifest that start with the specified +path+ at a specified +revision+.
33
33
  # Latest version of the manifest is used if +revision+ is ommitted.
34
34
  #
35
- # == Example:
35
+ # === Example:
36
36
  # repository.manifest.scan_for_path('/')
37
37
  # repository.manifest.scan_for_path('some-interesting-directory/', '2d32410d9629')
38
38
  #
@@ -1,13 +1,9 @@
1
1
  module Mercurial
2
2
 
3
3
  #
4
- # The class represents Mercurial file or directory. Data obtained by scanning +hg manifest+ output.
4
+ # This class represents a file or a directory stored inside a repository. The data is provided by {Mercurial::Manifest Manifest}.
5
5
  #
6
- # The class represents Node object itself, {Mercurial::NodeFactory NodeFactory} is responsible
7
- # for assembling instances of Node. For the list of all possible branch-related operations please
8
- # look documentation for {Mercurial::NodeFactory NodeFactory}.
9
- #
10
- # Additionally {Mercurial::Manifest Manifest} is responsible for reading and scanning the manifest.
6
+ # To see how Node instances are assembled, check the {Mercurial::NodeFactory NodeFactory}.
11
7
  #
12
8
  class Node
13
9
  include Mercurial::Helper
@@ -1,12 +1,28 @@
1
1
  module Mercurial
2
2
  class RepositoryNotFound < Error; end
3
3
 
4
+ #
5
+ # This class represents a Mercurial repository. Most of the time you will use this as a proxy for
6
+ # all your hg operations.
7
+ #
4
8
  class Repository
5
9
 
10
+ #
11
+ # Creates a new repository on disk. Returns a {Mercurial::Repository Repository} instance.
12
+ #
13
+ # === Example:
14
+ # Mercurial::Repository.create("/Users/ilya/Desktop/cool_repository")
15
+ #
6
16
  def self.create(destination)
7
17
  init_repository(destination)
8
18
  end
9
19
 
20
+ #
21
+ # Opens an existing repository on disk. Returns a {Mercurial::Repository Repository} instance.
22
+ #
23
+ # === Example:
24
+ # Mercurial::Repository.open("/Users/ilya/Desktop/existing-repo")
25
+ #
10
26
  def self.open(destination)
11
27
  if File.exists?(destination)
12
28
  new(destination)
@@ -15,6 +31,12 @@ module Mercurial
15
31
  end
16
32
  end
17
33
 
34
+ #
35
+ # Creates a clone of an existing repository via URL.
36
+ #
37
+ # === Example:
38
+ # Mercurial::Repository.clone("file:///Users/ilya/Desktop/existing-repo", "/path/to/the/clone")
39
+ #
18
40
  def self.clone(url, destination, cmd_options)
19
41
  create_destination(destination)
20
42
  opts = cmd_options.merge(:append_hg => true)
@@ -26,50 +48,86 @@ module Mercurial
26
48
  @path = source
27
49
  end
28
50
 
51
+ #
52
+ # Returns an instance of {Mercurial::Shell Shell} attached to the repository.
53
+ #
29
54
  def shell
30
55
  @_shell ||= Mercurial::Shell.new(self)
31
56
  end
32
57
 
58
+ #
59
+ # Returns an instance of {Mercurial::ConfigFile ConfigFile} attached to the repository.
60
+ #
33
61
  def config
34
62
  @_config ||= Mercurial::ConfigFile.new(self)
35
63
  end
36
64
 
65
+ #
66
+ # Returns an instance of {Mercurial::HookFactory HookFactory} attached to the repository.
67
+ #
37
68
  def hooks
38
69
  @_hook_factory ||= Mercurial::HookFactory.new(self)
39
70
  end
40
71
 
72
+ #
73
+ # Returns an instance of {Mercurial::CommitFactory CommitFactory} attached to the repository.
74
+ #
41
75
  def commits
42
76
  @_commits ||= Mercurial::CommitFactory.new(self)
43
77
  end
44
78
 
79
+ #
80
+ # Returns an instance of {Mercurial::BranchFactory BranchFactory} attached to the repository.
81
+ #
45
82
  def branches
46
83
  @_branches ||= Mercurial::BranchFactory.new(self)
47
84
  end
48
85
 
86
+ #
87
+ # Returns an instance of {Mercurial::TagFactory TagFactory} attached to the repository.
88
+ #
49
89
  def tags
50
90
  @_tags ||= Mercurial::TagFactory.new(self)
51
91
  end
52
92
 
93
+ #
94
+ # Returns an instance of {Mercurial::DiffFactory DiffFactory} attached to the repository.
95
+ #
53
96
  def diffs
54
97
  @_diffs ||= Mercurial::DiffFactory.new(self)
55
98
  end
56
99
 
100
+ #
101
+ # Returns an instance of {Mercurial::NodeFactory NodeFactory} attached to the repository.
102
+ #
57
103
  def nodes
58
104
  @_nodes ||= Mercurial::NodeFactory.new(self)
59
105
  end
60
106
 
107
+ #
108
+ # Returns an instance of {Mercurial::BlameFactory BlameFactory} attached to the repository.
109
+ #
61
110
  def blames
62
111
  @_blames ||= Mercurial::BlameFactory.new(self)
63
112
  end
64
113
 
114
+ #
115
+ # Returns an instance of {Mercurial::Manifest Manifest} attached to the repository.
116
+ #
65
117
  def manifest
66
118
  @_manifest ||= Mercurial::Manifest.new(self)
67
119
  end
68
120
 
121
+ #
122
+ # Returns an instance of {Mercurial::FileIndex FileIndex} attached to the repository.
123
+ #
69
124
  def file_index
70
125
  @_file_index ||= Mercurial::FileIndex.new(self)
71
126
  end
72
127
 
128
+ #
129
+ # Shortcut for +nodes.find+.
130
+ #
73
131
  def node(name, hash_id)
74
132
  nodes.find(name, hash_id)
75
133
  end
@@ -78,17 +136,29 @@ module Mercurial
78
136
  self.class.clone(file_system_url, destination_path, cmd_options)
79
137
  end
80
138
 
139
+ #
140
+ # Pull from an origin.
141
+ #
142
+ # === Example:
143
+ # repository.pull
144
+ #
81
145
  def pull(origin='default', cmd_options={})
82
146
  shell.hg(['pull ?', origin], cmd_options)
83
147
  end
84
148
 
149
+ #
150
+ # Run +hg verify+ on the repository. Returns +true+ if verified, +false+ otherwise.
151
+ #
85
152
  def verify
86
153
  shell.hg('verify')
87
154
  true
88
155
  rescue Mercurial::CommandError
89
156
  false
90
157
  end
91
-
158
+
159
+ #
160
+ # Returns an array of repository's paths (as remotes).
161
+ #
92
162
  def paths
93
163
  {}.tap do |result|
94
164
  shell.hg('paths').each do |line|
@@ -98,6 +168,9 @@ module Mercurial
98
168
  end
99
169
  end
100
170
 
171
+ #
172
+ # Deletes the repository from disk.
173
+ #
101
174
  def destroy!
102
175
  FileUtils.rm_rf(path)
103
176
  end
@@ -118,6 +191,21 @@ module Mercurial
118
191
  File.mtime(dothg_path).to_i
119
192
  end
120
193
 
194
+ #
195
+ # Accepts a block, executes all commands inside the block with caching disabled.
196
+ #
197
+ # === Example:
198
+ #
199
+ # repository.no_cache do
200
+ # repository.commits.all
201
+ # repository.branches.all
202
+ # end
203
+ #
204
+ # Same as:
205
+ #
206
+ # repository.commits.all :cache => false
207
+ # repository.branches.all :cache => false
208
+ #
121
209
  def no_cache
122
210
  @cache_disabled_by_override = true
123
211
  yield
@@ -1,9 +1,56 @@
1
1
  module Mercurial
2
2
 
3
+ #
4
+ # This is a tiny helper class that makes it simple for you to execute shell commands.
5
+ # Use it to execute hg commands that don't have a proper wrappers yet.
6
+ #
3
7
  class Shell
4
8
 
5
9
  attr_reader :repository
6
10
 
11
+ #
12
+ # Creates a {Mercurial::Command Command} instance and executes it. Supports a few neat options:
13
+ #
14
+ # ==== :append_hg
15
+ #
16
+ # You don't have to worry about specifying a correct path to your hg binary every time you want to execute a command:
17
+ #
18
+ # Shell.run("help", :append_hg => true)
19
+ #
20
+ # ==== Arguments interpolation
21
+ #
22
+ # Interpolation make your commands secure by escaping dangerous characters and wrapping everything in quotes:
23
+ #
24
+ # Shell.run(["clone ? ?", url, destination], :append_hg => true)
25
+ #
26
+ # ==== :in
27
+ #
28
+ # Allows you to execute commands in a specific directory:
29
+ #
30
+ # Shell.run('log', :in => repository_path)
31
+ #
32
+ # ==== :pipe
33
+ #
34
+ # Gives you piping flexibility:
35
+ #
36
+ # Shell.run('log', :pipe => "grep '9:0f41dd2ec166' -wc", :in => repository_path)
37
+ #
38
+ # Same as running +hg log | grep '9:0f41dd2ec166' -wc+
39
+ #
40
+ # ==== :timeout
41
+ #
42
+ # Specify a timeout in seconds for your command:
43
+ #
44
+ # Shell.run("/usr/bin/long-running-task", :timeout => 5)
45
+ #
46
+ # +Timeout::Error+ will be raised on timeout.
47
+ #
48
+ # ==== :cache
49
+ #
50
+ # Caching is enabled by default for all commands. Use this setting to avoid it:
51
+ #
52
+ # Shell.run("init", :append_hg => true, :cache => false)
53
+ #
7
54
  def self.run(cmd, options={})
8
55
  build = []
9
56
 
@@ -33,13 +80,16 @@ module Mercurial
33
80
  @repository = repository
34
81
  end
35
82
 
83
+ #
84
+ # This method is a shortcut to +Shell.run(cmd, :append_hg => true, :in => repository.path)+.
85
+ #
36
86
  def hg(cmd, options={})
37
87
  options[:in] ||= repository.path
38
88
  options[:repository] = repository
39
89
  options[:append_hg] = true
40
90
  run(cmd, options)
41
91
  end
42
-
92
+
43
93
  def run(cmd, options={})
44
94
  self.class.run(cmd, options)
45
95
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mercurial-ruby}
8
- s.version = "0.7.0"
8
+ s.version = "0.7.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ilya Sabanin"]
12
- s.date = %q{2012-03-02}
12
+ s.date = %q{2012-03-05}
13
13
  s.description = %q{Ruby API for Mercurial DVCS.}
14
14
  s.email = %q{ilya.sabanin@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -92,6 +92,7 @@ Gem::Specification.new do |s|
92
92
  s.specification_version = 3
93
93
 
94
94
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
95
+ s.add_runtime_dependency(%q<open4>, ["~> 1.3.0"])
95
96
  s.add_development_dependency(%q<minitest>, [">= 0"])
96
97
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
97
98
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -99,6 +100,7 @@ Gem::Specification.new do |s|
99
100
  s.add_development_dependency(%q<mocha>, ["~> 0.9"])
100
101
  s.add_development_dependency(%q<ruby-debug>, ["~> 0.10"])
101
102
  else
103
+ s.add_dependency(%q<open4>, ["~> 1.3.0"])
102
104
  s.add_dependency(%q<minitest>, [">= 0"])
103
105
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
104
106
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -107,6 +109,7 @@ Gem::Specification.new do |s|
107
109
  s.add_dependency(%q<ruby-debug>, ["~> 0.10"])
108
110
  end
109
111
  else
112
+ s.add_dependency(%q<open4>, ["~> 1.3.0"])
110
113
  s.add_dependency(%q<minitest>, [">= 0"])
111
114
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
112
115
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
data/test/test_command.rb CHANGED
@@ -16,6 +16,16 @@ describe Mercurial::Command do
16
16
  Mercurial::Command.new("cd #{ @repository.path } && hg shikaka").execute
17
17
  }.must_raise Mercurial::CommandError
18
18
  end
19
+
20
+ it "should not translate exit status of zero with shell errors to ruby exceptions" do
21
+ Mercurial::Command.new("echo stderr >&2 && echo stdout && exit 0").execute.strip.must_equal "stdout"
22
+ end
23
+
24
+ it "should translate exit status of non-zero with shell errors to ruby exceptions" do
25
+ lambda{
26
+ Mercurial::Command.new("echo stderr >&2 && echo stdout && exit 1").execute
27
+ }.must_raise Mercurial::CommandError
28
+ end
19
29
 
20
30
  it "should execute commands with timeout" do
21
31
  Mercurial.configuration.stubs(:shell_timeout).returns(1)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mercurial-ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 7
9
- - 0
10
- version: 0.7.0
9
+ - 1
10
+ version: 0.7.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ilya Sabanin
@@ -15,14 +15,30 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-02 00:00:00 -05:00
18
+ date: 2012-03-05 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: open4
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 27
31
+ segments:
32
+ - 1
33
+ - 3
34
+ - 0
35
+ version: 1.3.0
36
+ requirement: *id001
21
37
  - !ruby/object:Gem::Dependency
22
38
  type: :development
23
39
  prerelease: false
24
40
  name: minitest
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
26
42
  none: false
27
43
  requirements:
28
44
  - - ">="
@@ -31,12 +47,12 @@ dependencies:
31
47
  segments:
32
48
  - 0
33
49
  version: "0"
34
- requirement: *id001
50
+ requirement: *id002
35
51
  - !ruby/object:Gem::Dependency
36
52
  type: :development
37
53
  prerelease: false
38
54
  name: bundler
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
57
  requirements:
42
58
  - - ~>
@@ -47,12 +63,12 @@ dependencies:
47
63
  - 0
48
64
  - 0
49
65
  version: 1.0.0
50
- requirement: *id002
66
+ requirement: *id003
51
67
  - !ruby/object:Gem::Dependency
52
68
  type: :development
53
69
  prerelease: false
54
70
  name: jeweler
55
- version_requirements: &id003 !ruby/object:Gem::Requirement
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
56
72
  none: false
57
73
  requirements:
58
74
  - - ~>
@@ -63,12 +79,12 @@ dependencies:
63
79
  - 6
64
80
  - 4
65
81
  version: 1.6.4
66
- requirement: *id003
82
+ requirement: *id004
67
83
  - !ruby/object:Gem::Dependency
68
84
  type: :development
69
85
  prerelease: false
70
86
  name: rcov
71
- version_requirements: &id004 !ruby/object:Gem::Requirement
87
+ version_requirements: &id005 !ruby/object:Gem::Requirement
72
88
  none: false
73
89
  requirements:
74
90
  - - ">="
@@ -77,12 +93,12 @@ dependencies:
77
93
  segments:
78
94
  - 0
79
95
  version: "0"
80
- requirement: *id004
96
+ requirement: *id005
81
97
  - !ruby/object:Gem::Dependency
82
98
  type: :development
83
99
  prerelease: false
84
100
  name: mocha
85
- version_requirements: &id005 !ruby/object:Gem::Requirement
101
+ version_requirements: &id006 !ruby/object:Gem::Requirement
86
102
  none: false
87
103
  requirements:
88
104
  - - ~>
@@ -92,12 +108,12 @@ dependencies:
92
108
  - 0
93
109
  - 9
94
110
  version: "0.9"
95
- requirement: *id005
111
+ requirement: *id006
96
112
  - !ruby/object:Gem::Dependency
97
113
  type: :development
98
114
  prerelease: false
99
115
  name: ruby-debug
100
- version_requirements: &id006 !ruby/object:Gem::Requirement
116
+ version_requirements: &id007 !ruby/object:Gem::Requirement
101
117
  none: false
102
118
  requirements:
103
119
  - - ~>
@@ -107,7 +123,7 @@ dependencies:
107
123
  - 0
108
124
  - 10
109
125
  version: "0.10"
110
- requirement: *id006
126
+ requirement: *id007
111
127
  description: Ruby API for Mercurial DVCS.
112
128
  email: ilya.sabanin@gmail.com
113
129
  executables: []