Mange-git-remote-monitor 0.1.0
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/HISTORY +15 -0
- data/LICENSE +23 -0
- data/README +33 -0
- data/Rakefile +47 -0
- data/TODO +23 -0
- data/VERSION.yml +4 -0
- data/bin/git-remote-monitor +127 -0
- data/lib/git_remote_monitor.rb +28 -0
- data/lib/git_remote_monitor/git_wrapper.rb +101 -0
- data/lib/git_remote_monitor/monitor.rb +60 -0
- data/lib/git_remote_monitor/notifier.rb +60 -0
- data/spec/git_remote_monitor/git_wrapper_spec.rb +109 -0
- data/spec/spec_helper.rb +9 -0
- metadata +76 -0
data/HISTORY
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
┌──────────────────────┐
|
2
|
+
│ Legend |
|
3
|
+
├──────────────────────┤
|
4
|
+
│ + = New feature |
|
5
|
+
| b = Fixed bug |
|
6
|
+
| * = General fix |
|
7
|
+
| - = Known regression |
|
8
|
+
└──────────────────────┘
|
9
|
+
|
10
|
+
VERSION 0.1
|
11
|
+
===========
|
12
|
+
+ Basic support for notifications
|
13
|
+
+ Basic fetch wrapper to git
|
14
|
+
+ Basic monitor, waiting 20 seconds between each fetch
|
15
|
+
+ Simple comparing remotes with local possible
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright © 2009
|
4
|
+
* Magnus Bergmark
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
git-remote-monitor
|
2
|
+
==================
|
3
|
+
|
4
|
+
Synopsis
|
5
|
+
--------
|
6
|
+
git-remote-monitor (grm) is a little daemon that scans your git remotes for changes and then notifies you when
|
7
|
+
it changes. This is useful when you are working on a piece of software together with other developers and you
|
8
|
+
want to merge with their changes often. It will also help you when using graphical tools like gitk, git-gui and
|
9
|
+
GitX since this will make your graphical tree refresh automatically.
|
10
|
+
|
11
|
+
Current state
|
12
|
+
-------------
|
13
|
+
In its current state, which is early alpha, grm is not actually a daemon. When it is more ready and stable, the
|
14
|
+
daemon capabilities will be added. Please see TODO for more information about the roadmap.
|
15
|
+
|
16
|
+
How does it work?
|
17
|
+
-----------------
|
18
|
+
In the background, grm does a git fetch at a regular interval. It then looks at your commits and how they relate
|
19
|
+
to your remote.
|
20
|
+
|
21
|
+
If it recognizes that the remote branch has been updated, it will tell you through Growl. In the future, grm will
|
22
|
+
use whichever system available in your OS when notifying you.
|
23
|
+
|
24
|
+
Dependencies
|
25
|
+
------------
|
26
|
+
To use this gem, you need to have the following:
|
27
|
+
* rubygems (Obviously)
|
28
|
+
* meow (Sends messages to Growl)
|
29
|
+
|
30
|
+
COPYRIGHT
|
31
|
+
=========
|
32
|
+
|
33
|
+
Copyright © 2009 Magnus Bergmark. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "git-remote-monitor"
|
9
|
+
s.summary = %Q{Monitor your remotes and get notifications on changes}
|
10
|
+
s.email = "magnus.bergmark@gmail.com"
|
11
|
+
s.homepage = "http://github.com/Mange/git-remote-monitor"
|
12
|
+
s.executables = 'git-remote-monitor'
|
13
|
+
|
14
|
+
s.description = %Q{git-remote-monitor is a little daemon that scans your git remotes for changes and then notifies you when
|
15
|
+
it changes. This is useful when you are working on a piece of software together with other developers and you
|
16
|
+
want to merge with their changes often. It will also help you when using graphical tools like gitk, git-gui and
|
17
|
+
GitX since this will make your graphical tree refresh automatically.}
|
18
|
+
|
19
|
+
s.files = FileList["[A-Z]*", "{bin,generators,lib,spec}/**/*"]
|
20
|
+
s.authors = ["Magnus Bergmark"]
|
21
|
+
s.add_dependency 'meow'
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new do |t|
|
28
|
+
t.libs << 'lib'
|
29
|
+
t.verbose = false
|
30
|
+
t.rcov = false
|
31
|
+
end
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new('rcov') do |t|
|
34
|
+
t.libs << 'lib'
|
35
|
+
t.verbose = false
|
36
|
+
t.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
rdoc.rdoc_dir = 'rdoc'
|
41
|
+
rdoc.title = 'git-remote-monitor'
|
42
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default => :test
|
data/TODO
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
TODO
|
2
|
+
====
|
3
|
+
|
4
|
+
Before beta:
|
5
|
+
* More specs
|
6
|
+
* Need to figure out how to simulate the stuff better; reduce inter-dependencies
|
7
|
+
* Command line arguments
|
8
|
+
* Specify a project name
|
9
|
+
* Specify path
|
10
|
+
* Specify fetch interval
|
11
|
+
* Daemonize the program
|
12
|
+
* Look at real Git libraries; might be better than calling the system
|
13
|
+
|
14
|
+
Before 1.0:
|
15
|
+
* Read/Save configuration with git-config(1)
|
16
|
+
* Make it easy to quit the daemons (git-remote-monitor --kill-all, or similar)
|
17
|
+
|
18
|
+
Before 1.1:
|
19
|
+
* Extend to more notification systems than Meow (Growl on Mac OS X)
|
20
|
+
* knotify
|
21
|
+
* Whatever Gnome uses
|
22
|
+
* Windows possible?
|
23
|
+
* XMPP? Too crazy?
|
data/VERSION.yml
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# git-remote-monitor(1)
|
4
|
+
#
|
5
|
+
# The MIT License
|
6
|
+
# Copyright © 2009
|
7
|
+
# * Magnus Bergmark
|
8
|
+
#
|
9
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
# of this software and associated documentation files (the "Software"), to deal
|
11
|
+
# in the Software without restriction, including without limitation the rights
|
12
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
# copies of the Software, and to permit persons to whom the Software is
|
14
|
+
# furnished to do so, subject to the following conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be included in
|
17
|
+
# all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
|
+
# THE SOFTWARE.
|
26
|
+
#
|
27
|
+
|
28
|
+
# Add ../lib/ as a load path in case we are doing development
|
29
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
30
|
+
|
31
|
+
REQUIRED_GEMS = ['rubygems', 'meow']
|
32
|
+
begin
|
33
|
+
REQUIRED_GEMS.each { |g| require g }
|
34
|
+
rescue LoadError => e
|
35
|
+
failed_gem = e.to_s.slice(/-- (.*)$/, 1)
|
36
|
+
$stderr.puts "ERROR: Could not load #{failed_gem}."
|
37
|
+
$stderr.puts "#{$0} needs the following gems:"
|
38
|
+
$stderr.puts REQUIRED_GEMS.collect { |g| "\t* #{g}" }.join("\n")
|
39
|
+
Kernel.exit(1)
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'git_remote_monitor'
|
43
|
+
require 'getoptlong'
|
44
|
+
require 'rdoc/usage'
|
45
|
+
|
46
|
+
$usage = %Q{
|
47
|
+
= Synopsis
|
48
|
+
Monitors the current branch's remote for changes at a fixed interval. Changes will be fetched and you will be
|
49
|
+
notified about how many commits you are behind.
|
50
|
+
|
51
|
+
= Usage
|
52
|
+
git remote-monitor [OPTIONS]
|
53
|
+
|
54
|
+
== Options
|
55
|
+
-h, --help:
|
56
|
+
displays this usage information
|
57
|
+
|
58
|
+
-i TIME, --interval=TIME:
|
59
|
+
time, in seconds, between each fetch. Defaults to 60 seconds.
|
60
|
+
|
61
|
+
== Daemon
|
62
|
+
Since this utility is in an early stage, no daemon capabilities have yet been added. It is recommended that
|
63
|
+
you start the command in the background (append a single & to the end of the command line) so you can keep
|
64
|
+
using your term to other things while the program is running.
|
65
|
+
}
|
66
|
+
|
67
|
+
#
|
68
|
+
# Usage information
|
69
|
+
#
|
70
|
+
# Shamefully stolen from RDoc#usage. We cannot use RDoc::usage because
|
71
|
+
# RubyGems will call this from a wrapper, and #usage is hardcoded to look
|
72
|
+
# at the top-level file instead of the current one. I have changed this
|
73
|
+
# code to instead just parse a string.
|
74
|
+
def usage_and_exit!
|
75
|
+
markup = SM::SimpleMarkup.new
|
76
|
+
flow_convertor = SM::ToFlow.new
|
77
|
+
|
78
|
+
flow = markup.convert($usage, flow_convertor)
|
79
|
+
|
80
|
+
options = RI::Options.instance
|
81
|
+
formatter = options.formatter.new(options, "")
|
82
|
+
formatter.display_flow(flow)
|
83
|
+
|
84
|
+
exit(0)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Command line arguments parser
|
89
|
+
#
|
90
|
+
def parse_command_line_arguments!
|
91
|
+
opts = GetoptLong.new(
|
92
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
93
|
+
[ '--interval', '-i', GetoptLong::REQUIRED_ARGUMENT]
|
94
|
+
)
|
95
|
+
|
96
|
+
opts.each do |opt, arg|
|
97
|
+
case opt
|
98
|
+
when '--help'
|
99
|
+
usage_and_exit!
|
100
|
+
when '--interval'
|
101
|
+
interval = arg.to_i
|
102
|
+
unless interval > 10
|
103
|
+
puts "ERROR: Interval must be larger than 10"
|
104
|
+
exit 1
|
105
|
+
end
|
106
|
+
$interval = interval
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Default values for the command line options
|
112
|
+
$interval = 60
|
113
|
+
|
114
|
+
begin
|
115
|
+
parse_command_line_arguments!
|
116
|
+
|
117
|
+
notifier = GitRemoteMonitor::Notifier.new
|
118
|
+
# Hardcoded values for now
|
119
|
+
monitor = GitRemoteMonitor::Monitor.new(Dir.pwd, $interval, notifier)
|
120
|
+
|
121
|
+
monitor.start_monitoring!
|
122
|
+
rescue => e
|
123
|
+
$stderr.puts "-- Unhandled Exception! ------"
|
124
|
+
$stderr.puts e
|
125
|
+
$stderr.puts e.backtrace
|
126
|
+
Kernel.exit(1)
|
127
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# The MIT License
|
2
|
+
# Copyright © 2009 Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
module GitRemoteMonitor
|
23
|
+
PATH = File.join(File.dirname(__FILE__), '..')
|
24
|
+
end
|
25
|
+
|
26
|
+
['git_wrapper', 'monitor', 'notifier'].each do |file|
|
27
|
+
require File.join(File.dirname(__FILE__), 'git_remote_monitor', file)
|
28
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# The MIT License
|
2
|
+
# Copyright © 2009 Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
class GitRemoteMonitor::GitWrapper
|
23
|
+
class << self
|
24
|
+
|
25
|
+
def local_branch
|
26
|
+
branches = call_get_local_branch.split("\n")
|
27
|
+
current = branches.detect { |branch| branch.strip.include? "* " }
|
28
|
+
return nil unless current
|
29
|
+
current.strip.slice(/^\* (.+)$/, 1)
|
30
|
+
end
|
31
|
+
|
32
|
+
def remote_branch
|
33
|
+
branch = self.local_branch
|
34
|
+
remote = call_get_remote(branch).strip
|
35
|
+
return nil if remote.empty?
|
36
|
+
"#{remote}/#{branch}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_tracking_info(our_branch, their_branch)
|
40
|
+
tracking_info = call_get_tracking_info(our_branch, their_branch).split("\n")
|
41
|
+
if tracking_info.size > 2
|
42
|
+
raise "Wrong number of lines returned while trying to look at tracking information!"
|
43
|
+
elsif tracking_info.size == 2
|
44
|
+
return [*tracking_info.collect { |line| line.gsub(/\D+/, '').to_i }]
|
45
|
+
else
|
46
|
+
# We have too look at which kind it is
|
47
|
+
tracking_info = tracking_info.first
|
48
|
+
if tracking_info and tracking_info.include? "<"
|
49
|
+
return [tracking_info.gsub(/\D+/, '').to_i, 0]
|
50
|
+
elsif tracking_info and tracking_info.include? ">"
|
51
|
+
return [0, tracking_info.gsub(/\D+/, '').to_i]
|
52
|
+
else
|
53
|
+
return [0, 0]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Calls "git fetch" on the current working directory. Raises an error in case this
|
60
|
+
# command ran unsuccessfully.
|
61
|
+
#
|
62
|
+
# The method will return true if a fetch was made or false if nothing was fetched.
|
63
|
+
#
|
64
|
+
def fetch!
|
65
|
+
# If the output was empty, no actual fetch was done
|
66
|
+
return !call_fetch.strip.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
# Do the actual system call for "git fetch", returning output
|
71
|
+
def call_fetch
|
72
|
+
output = `git fetch 2>&1`
|
73
|
+
raise "Could not fetch from remote! " + output unless $?.success?
|
74
|
+
output
|
75
|
+
end
|
76
|
+
|
77
|
+
# Asks Git about tracking information for the given local branch and the specified
|
78
|
+
# remote branch.
|
79
|
+
#
|
80
|
+
# Returns output formatted by `uniq -c` after looking at a list of commits
|
81
|
+
# It should contain between 1 and 2 lines inclusive and look like this:
|
82
|
+
# 4 <
|
83
|
+
# 1 >
|
84
|
+
#
|
85
|
+
# * The lines will be indented by spaces, then have a number, a space and a symbol.
|
86
|
+
# * When no branch have moved, the output will be on 1 line and have a 1 as the number
|
87
|
+
# and no symbol.
|
88
|
+
# * The symbols mean the following: "<" means local commits, ">" means remote commits
|
89
|
+
def call_get_tracking_info(our, their)
|
90
|
+
`git rev-list --left-right #{our}...#{their} | cut -c 1 | sort | uniq -c`
|
91
|
+
end
|
92
|
+
|
93
|
+
def call_get_local_branch
|
94
|
+
`git branch --no-color`
|
95
|
+
end
|
96
|
+
|
97
|
+
def call_get_remote(local_name)
|
98
|
+
`git config branch.#{local_name}.remote`
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# The MIT License
|
2
|
+
# Copyright © 2009 Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
#
|
23
|
+
# Monitor takes care of monitoring a specific directory for changes and then notifying a specified
|
24
|
+
# instance about the changes later on.
|
25
|
+
#
|
26
|
+
class GitRemoteMonitor::Monitor
|
27
|
+
def initialize(directory, interval, notifier, name = nil)
|
28
|
+
@directory = directory
|
29
|
+
@name = name || File.basename(directory)
|
30
|
+
@interval = interval.to_i
|
31
|
+
@notifier = notifier
|
32
|
+
|
33
|
+
move_to_directory!(@directory)
|
34
|
+
end
|
35
|
+
|
36
|
+
def start_monitoring!
|
37
|
+
while true
|
38
|
+
notify! if GitRemoteMonitor::GitWrapper.fetch!
|
39
|
+
sleep @interval
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def notify!
|
46
|
+
# Find out the status
|
47
|
+
local = GitRemoteMonitor::GitWrapper.local_branch
|
48
|
+
remote = GitRemoteMonitor::GitWrapper.remote_branch
|
49
|
+
my_commits, their_commits = GitRemoteMonitor::GitWrapper.get_tracking_info(local, remote)
|
50
|
+
@notifier.notify_commits(@name, local, my_commits, their_commits)
|
51
|
+
end
|
52
|
+
|
53
|
+
def move_to_directory!(directory)
|
54
|
+
unless File.exist?(directory) and File.directory?(directory)
|
55
|
+
raise "#{directory} not found or not a directory"
|
56
|
+
end
|
57
|
+
Dir.chdir(directory)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# The MIT License
|
2
|
+
# Copyright © 2009 Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
class GitRemoteMonitor::Notifier
|
23
|
+
|
24
|
+
def initialize()
|
25
|
+
# TODO: Auto-discover notification systems and load the one the user have
|
26
|
+
# For now, just use meow. REMEMBER: Remove 'meow' from the bin/ script when
|
27
|
+
# this requirement changes here!
|
28
|
+
|
29
|
+
require 'meow'
|
30
|
+
@notifier = ::Meow.new('git-remote-monitor')
|
31
|
+
end
|
32
|
+
|
33
|
+
def notify_commits(name, branch_name, local_commits, remote_commits)
|
34
|
+
message = get_message(local_commits, remote_commits)
|
35
|
+
if message
|
36
|
+
@notifier.notify("#{name} (#{branch_name})", message, :icon => "#{GitRemoteMonitor::PATH}/images/git-logo.png")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def get_message(local_commits, remote_commits)
|
42
|
+
# If there aren't any commits on the remote, we just ignore
|
43
|
+
# this difference. It's because we don't want to notify the user
|
44
|
+
# that they are x commits before the remote.
|
45
|
+
unless remote_commits == 0
|
46
|
+
|
47
|
+
# Now, we can have this scenarios:
|
48
|
+
# 1. The branch has not diverged; user has no commits, but remote has.
|
49
|
+
# 2. The branch has diverged; both the user and the remote has commits
|
50
|
+
message = if local_commits > 0
|
51
|
+
"Diverged! Remote has #{remote_commits} new commits, and you have #{local_commits} commits to push."
|
52
|
+
else
|
53
|
+
"Remote got updated! Now #{remote_commits} commits in front of you."
|
54
|
+
end
|
55
|
+
return message
|
56
|
+
end
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# The MIT License
|
2
|
+
# Copyright © 2009 Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
require File.dirname(__FILE__) + '/../../lib/git_remote_monitor'
|
23
|
+
|
24
|
+
describe GitRemoteMonitor::GitWrapper do
|
25
|
+
|
26
|
+
before(:all) do
|
27
|
+
# Shortcut :-D
|
28
|
+
@wrapper = GitRemoteMonitor::GitWrapper
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "fetch" do
|
32
|
+
it "should know if a fetch didn't occur" do
|
33
|
+
@wrapper.should_receive(:call_fetch).and_return "\n"
|
34
|
+
@wrapper.fetch!.should == false
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should know if a fetch occured" do
|
38
|
+
@wrapper.should_receive(:call_fetch).and_return(
|
39
|
+
"remote: Generating pack...\n" +
|
40
|
+
"remote: Done counting 119 objects.\n" +
|
41
|
+
"remote: Result has 90 objects.\n" +
|
42
|
+
"remote: Deltifying 90 objects.\n" +
|
43
|
+
"remote: 100% (90/90) done\n" +
|
44
|
+
"remote: Total 90, written 90 (delta 55), reused 0 (delta 0)\n" +
|
45
|
+
"Unpacking objects: 100% (90/90), done.\n" +
|
46
|
+
"From git@foobar:baz\n" +
|
47
|
+
" e871819..110f4bc master -> origin/master\n"
|
48
|
+
)
|
49
|
+
|
50
|
+
@wrapper.fetch!.should == true
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "branch discovery" do
|
56
|
+
before(:each) do
|
57
|
+
@wrapper.stub!(:call_get_remote).and_return ""
|
58
|
+
|
59
|
+
@wrapper.stub!(:call_get_local_branch).and_return " * master"
|
60
|
+
@wrapper.stub!(:call_get_remote).with("master").and_return "upstream\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should find the current local branch" do
|
64
|
+
@wrapper.local_branch.should == "master"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should find the current local branch, even if there are many branches" do
|
68
|
+
@wrapper.stub!(:call_get_local_branch).and_return(" master\n* test\n other")
|
69
|
+
@wrapper.local_branch.should == "test"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should find the remote branch" do
|
73
|
+
@wrapper.remote_branch.should == "upstream/master"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return nil when no remote branch exists" do
|
77
|
+
@wrapper.stub!(:call_get_local_branch).and_return "local"
|
78
|
+
@wrapper.remote_branch.should be_nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
describe "getting tracking information" do
|
84
|
+
|
85
|
+
before(:each) do
|
86
|
+
@wrapper.stub!(:call_get_tracking_info).and_return " 1 "
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be able to get the correct number of commits when nothing has changed" do
|
90
|
+
@wrapper.get_tracking_info("me", "you").should == [0, 0]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should be able to get the correct number of commits when diverged" do
|
94
|
+
@wrapper.should_receive(:call_get_tracking_info).and_return(" 1 <\n 7 >")
|
95
|
+
@wrapper.get_tracking_info("me", "you").should == [1, 7]
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should be able to get the correct number of commits when remote is ahead" do
|
99
|
+
@wrapper.should_receive(:call_get_tracking_info).and_return(" 7 >")
|
100
|
+
@wrapper.get_tracking_info("me", "you").should == [0, 7]
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should be able to get the correct number of commits when remote is behind" do
|
104
|
+
@wrapper.should_receive(:call_get_tracking_info).and_return(" 1 <")
|
105
|
+
@wrapper.get_tracking_info("me", "you").should == [1, 0]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Mange-git-remote-monitor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Magnus Bergmark
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-03 00:00:00 -08:00
|
13
|
+
default_executable: git-remote-monitor
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: meow
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: git-remote-monitor is a little daemon that scans your git remotes for changes and then notifies you when it changes. This is useful when you are working on a piece of software together with other developers and you want to merge with their changes often. It will also help you when using graphical tools like gitk, git-gui and GitX since this will make your graphical tree refresh automatically.
|
25
|
+
email: magnus.bergmark@gmail.com
|
26
|
+
executables:
|
27
|
+
- git-remote-monitor
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- HISTORY
|
34
|
+
- LICENSE
|
35
|
+
- Rakefile
|
36
|
+
- README
|
37
|
+
- TODO
|
38
|
+
- VERSION.yml
|
39
|
+
- bin/git-remote-monitor
|
40
|
+
- lib/git_remote_monitor
|
41
|
+
- lib/git_remote_monitor/git_wrapper.rb
|
42
|
+
- lib/git_remote_monitor/monitor.rb
|
43
|
+
- lib/git_remote_monitor/notifier.rb
|
44
|
+
- lib/git_remote_monitor.rb
|
45
|
+
- spec/git_remote_monitor
|
46
|
+
- spec/git_remote_monitor/git_wrapper_spec.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/Mange/git-remote-monitor
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --inline-source
|
53
|
+
- --charset=UTF-8
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.2.0
|
72
|
+
signing_key:
|
73
|
+
specification_version: 2
|
74
|
+
summary: Monitor your remotes and get notifications on changes
|
75
|
+
test_files: []
|
76
|
+
|