technomancy-conspire 0.1.0 → 0.1.2

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.
@@ -1,6 +1,14 @@
1
- === 0.0.1 / 2008-07-22
1
+ === 0.1.1 / 2008-07-25
2
2
 
3
- * 1 major enhancement
3
+ * Fixed a bug where empty repositories would not sync.
4
+ * Lower sync intervals by default.
5
+ * Emacs support works on a per-buffer basis.
4
6
 
5
- * Birthday!
7
+ === 0.1.0 / 2008-07-24
8
+
9
+ * Nearly usable! Sorta-works!
10
+
11
+ === 0.0.1 / 2008-07-23
12
+
13
+ * Birthday!
6
14
 
@@ -4,6 +4,7 @@ Manifest.txt
4
4
  README.rdoc
5
5
  Rakefile
6
6
  bin/conspire
7
+ conspire.gemspec
7
8
  lib/conspire.rb
8
9
  lib/conspire/conspirator.rb
9
10
  lib/conspire/gitjour_exts.rb
@@ -1,6 +1,7 @@
1
1
  = conspire
2
- by Phil Hagelberg (C) 2008
3
- http://conspire.rubyforge.org
2
+
3
+ (c) 2008 Phil Hagelberg
4
+ http://github.com/technomancy/conspire
4
5
 
5
6
  Conspire is a real-time collaborative editing platform using Git as a
6
7
  transport layer.
@@ -21,17 +22,18 @@ Once prerequisites are met:
21
22
  == Usage
22
23
 
23
24
  Conspiracy sessions operate around repositories rather than single
24
- files like other collaborative editors. So launch +conspire+ with a
25
- directory as its first argument to have it initialize a repository in
26
- that directory. From there you should open up your editor and invoke
27
- conspire from there on the files with which you wish to collaborate.
28
-
29
- See lib/conspire/support to see which editors are supported. In Emacs,
30
- install conspire.el and then visit the file you want to edit and
31
- pressing M-x conspire-mode.
25
+ files like other collaborative editors. See lib/conspire/support to
26
+ see which editors are supported. In Emacs, first install conspire.el,
27
+ then visit the file you want to edit and invoke M-x conspire-mode.
32
28
 
33
29
  Repository history is cleared in between conspiracy sessions.
34
30
 
31
+ You can manually use conspire if you want to try it out without an
32
+ editor. Just launch +conspire+ with a directory as its only argument,
33
+ and it will initialize a new git repository in there and launch a
34
+ conspiracy session. You will have to manually "git add" new files you
35
+ want to introduce to the session.
36
+
35
37
  For testing purposes, you can run two or more conspiracies on the same
36
38
  machine; you just have to specify an alternate port and name for the
37
39
  others. Names should always include the string "conspiracy" to
@@ -45,13 +47,19 @@ Set the DEBUG environment variable to get more information on the console.
45
47
 
46
48
  * Conflict resolution remains entirely unhandled.
47
49
 
50
+ * Emacs is the only supported editor; see below.
51
+
48
52
  * When using Avahi for your ZeroConf implementation, you will not be
49
53
  able to do anything unless you have an active network connection. So
50
54
  disconnected conspirancy sessions are not possible without bringing
51
55
  up an ad-hoc network to trick Avahi into activating. You'll also see
52
56
  a big fat warning, which should be ignored.
53
57
 
54
- == Editor Support
58
+ == Contributing
59
+
60
+ Patches are welcome via github or email. Adding support for more
61
+ editors would probably be the most useful contributions, though
62
+ anything is appreciated.
55
63
 
56
64
  Editors must support:
57
65
 
@@ -59,11 +67,6 @@ Editors must support:
59
67
  * Committing files to the repo
60
68
  * Refreshing internal buffers
61
69
 
62
- Edits should not be allowed in between these steps.
63
-
64
- Editors may be able to support launching the +conspire+ executable for
65
- added convenience.
66
-
67
- That's about all there is to it. If your favourite editor is not
68
- supported, please fork and add support for it; it's really not a
69
- difficult task.
70
+ Edits should not be allowed in between these steps. Editors may be
71
+ able to support launching the +conspire+ executable for added
72
+ convenience.
data/Rakefile CHANGED
@@ -7,17 +7,13 @@ require './lib/conspire.rb'
7
7
  Hoe.new('conspire', Conspire::VERSION) do |p|
8
8
  p.developer('Phil Hagelberg', 'technomancy@gmail.com')
9
9
 
10
+ # TODO: tell flog about README.rdoc instead of README.txt
10
11
  p.summary = 'Conspire is a real-time collaborative editing platform using Git as a transport layer.'
11
- p.url = 'http://conspire.rubyforge.org'
12
+ p.url = 'http://github.com/technomancy/conspire'
12
13
 
14
+ # TODO: release on rubyforge once all our required dependency versions make it to rubyforge
13
15
  p.extra_deps << ['technomancy-gitjour', '6.3.0']
14
- p.extra_deps << 'clip'
15
- end
16
-
17
- desc "Code statistics"
18
- task :stats do
19
- require 'code_statistics'
20
- CodeStatistics.new(['lib'], ['Unit tests', 'test']).to_s
16
+ p.extra_deps << 'alexvollmer-clip'
21
17
  end
22
18
 
23
19
  # vim: syntax=Ruby
@@ -9,6 +9,17 @@ options = Clip do |c|
9
9
  :default => Conspire::DEFAULTS[:sync_interval])
10
10
  c.optional('n', 'name', :desc => "Session name; must include 'conspiracy'",
11
11
  :default => Conspire::DEFAULTS[:name])
12
+ c.flag('v', 'version', :desc => 'Print version number and exit')
13
+ end
14
+
15
+ # TODO: show usage message on --help
16
+ if !options.valid?
17
+ puts "Conspire is a git-based collaboration platform."
18
+ puts " You generally interact use it via an editor; see README for details."
19
+ abort options.to_s
20
+ elsif options.version?
21
+ puts "conspire #{Conspire::VERSION}"
22
+ exit 0
12
23
  end
13
24
 
14
25
  Conspire.start ARGV.first, options
@@ -0,0 +1,40 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{conspire}
3
+ s.version = "0.1.2"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Phil Hagelberg"]
7
+ s.date = %q{2008-08-12}
8
+ s.default_executable = %q{conspire}
9
+ s.email = ["technomancy@gmail.com"]
10
+ s.executables = ["conspire"]
11
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
12
+ s.files = ["COPYING", "History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "bin/conspire", "conspire.gemspec", "lib/conspire.rb", "lib/conspire/conspirator.rb", "lib/conspire/gitjour_exts.rb", "lib/conspire/support/conspire.el", "test/perf.rb", "test/test_conspire.rb"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://github.com/technomancy/conspire}
15
+ s.rdoc_options = ["--main", "README.txt"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{conspire}
18
+ s.rubygems_version = %q{1.2.0}
19
+ s.summary = %q{Conspire is a real-time collaborative editing platform using Git as a transport layer.}
20
+ s.test_files = ["test/test_conspire.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<technomancy-gitjour>, ["= 6.3.0"])
28
+ s.add_runtime_dependency(%q<alexvollmer-clip>, [">= 0"])
29
+ s.add_development_dependency(%q<hoe>, [">= 1.7.0"])
30
+ else
31
+ s.add_dependency(%q<technomancy-gitjour>, ["= 6.3.0"])
32
+ s.add_dependency(%q<alexvollmer-clip>, [">= 0"])
33
+ s.add_dependency(%q<hoe>, [">= 1.7.0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<technomancy-gitjour>, ["= 6.3.0"])
37
+ s.add_dependency(%q<alexvollmer-clip>, [">= 0"])
38
+ s.add_dependency(%q<hoe>, [">= 1.7.0"])
39
+ end
40
+ end
@@ -1,17 +1,17 @@
1
- $LOAD_PATH << File.dirname(__FILE__)
2
1
  require 'set'
3
2
  require 'fileutils'
4
3
 
5
4
  require 'rubygems'
6
5
  require 'gitjour' # TODO: can we get rid of the avahi compatibility warning?
7
6
 
8
- require 'conspire/gitjour_exts'
9
- require 'conspire/conspirator'
7
+ require File.dirname(__FILE__) + '/conspire/gitjour_exts'
8
+ require File.dirname(__FILE__) + '/conspire/conspirator'
10
9
 
11
10
  module Conspire
12
- VERSION = '0.1.0'
13
- DEFAULTS = { :port => 7456, :name => 'conspiracy', :sync_interval => 0.5 }
14
- HOSTNAME = `hostname`.chomp
11
+ VERSION = '0.1.2'
12
+ # TODO: play with optimal intervals; perhaps auto-adjust based on latency?
13
+ DEFAULTS = { :port => 7456, :name => 'conspiracy', :sync_interval => 0.25 }
14
+ HOSTNAME = `hostname`.chomp # TODO: is there a better way?
15
15
 
16
16
  @conspirators = Set.new
17
17
 
@@ -19,9 +19,10 @@ module Conspire
19
19
 
20
20
  # Begin a conspiracy session
21
21
  def start(path, options)
22
- @options = options
23
- @path = path
22
+ @path, @options = path, options
23
+
24
24
  Gitjour::Application.init @path
25
+
25
26
  @thread = Thread.new do
26
27
  Gitjour::Application.serve(@path, @options.name, @options.port)
27
28
  end
@@ -39,6 +40,7 @@ module Conspire
39
40
  end
40
41
  end
41
42
 
43
+ # Sync with all conspirators, dropping the problematic ones
42
44
  def sync_all
43
45
  @conspirators.map do |c|
44
46
  begin
@@ -55,9 +57,6 @@ module Conspire
55
57
  end
56
58
 
57
59
  def discover_loop
58
- loop do
59
- Conspire.discover
60
- puts Conspire.conspirators.map{ |c| c.to_s } if ENV['DEBUG']
61
- end
60
+ loop { discover and (p @conspirators if ENV['DEBUG']) }
62
61
  end
63
62
  end
@@ -1,27 +1,25 @@
1
1
  module Conspire
2
2
  class Conspirator
3
- attr_accessor :last_synced, :host, :port, :name
3
+ attr_accessor :host, :port, :name
4
4
 
5
- def initialize(host, port, name = DEFAULTS[:name])
6
- @host, @port, @name = host[0 .. -2], port || DEFAULTS[:port], name
5
+ def initialize(host, port, name)
6
+ # host has a trailing dot; remove it
7
+ @host, @port, @name = host[0 .. -2], port, name
7
8
  end
8
9
 
9
10
  def sync(path)
10
- # TODO: figure out conflictless rebasing... evan?
11
- success = if ENV['DEBUG']
12
- puts "cd #{path} && git pull --rebase #{url}"
13
- system "cd #{path} && git pull --rebase #{url}"
14
- else
15
- system "cd #{path} && git pull --rebase #{url} &> /dev/null"
16
- end
17
-
18
- raise "could not rebase from #{url}" if ! success
19
- # @last_synced = Time.now # is this useful?
11
+ # TODO: figure out conflictless rebasing; new content always wins. evan?
12
+ if ENV['DEBUG']
13
+ puts "cd #{path} && git pull --rebase #{url}"
14
+ system "cd #{path} && git pull --rebase #{url}"
15
+ else
16
+ system "cd #{path} && git pull --rebase #{url} &> /dev/null"
17
+ end or raise "could not rebase from #{url}" if ! success
20
18
  end
21
19
 
22
20
  def url; "git://#{@host}:#{@port}/" end
23
-
24
21
  alias_method :to_s, :url
22
+ alias_method :inspect, :url
25
23
 
26
24
  # For set equality
27
25
  def eql?(other); self.url == other.url end
@@ -5,9 +5,12 @@ module Gitjour
5
5
 
6
6
  def init(path)
7
7
  abort "Repository already exists: #{path}" if File.exist? path + '/.git'
8
- at_exit { FileUtils.rm_rf path + '/.git' } unless ENV['KEEP']
8
+
9
9
  `mkdir -p #{path} && cd #{path} && git init`
10
- `touch #{path}/.git/git-daemon-export-ok`
10
+ FileUtils.touch ["#{path}/.git/git-daemon-export-ok", "#{path}/.conspire"]
11
+ `cd #{path}; git add .conspire; git commit -m "initial"`
12
+
13
+ at_exit { FileUtils.rm_rf [path + '/.git', path + '/.conspire'] } unless ENV['KEEP']
11
14
  end
12
15
 
13
16
  def puts(*args); end unless ENV['DEBUG']
@@ -3,7 +3,7 @@
3
3
  ;; Copyright (C) 2008 Phil Hagelberg
4
4
 
5
5
  ;; Author: Phil Hagelberg <technomancy@gmail.com>
6
- ;; URL: http://conspire.rubyforge.org
6
+ ;; URL: http://github.com/technomancy/conspire
7
7
  ;; Version: 0.2
8
8
  ;; Created: 2008-07-22
9
9
  ;; Keywords: collaboration
@@ -37,30 +37,22 @@
37
37
  ;;
38
38
  ;; (autoload 'conspire-mode "conspire" "Collaborative editing" t)
39
39
 
40
- ;;; TODO:
41
-
42
- ;; Automatically launch conspire executable.
43
- ;; Color lines based on which conspirator wrote them?
40
+ ;; TODO: For some reason conspire-sync-buffer only runs on cursor movement
41
+ ;; TODO: Gracefully kill shell process so it can clean up
42
+ ;; TODO: Don't bother with *Async Shell Command* output buffer
43
+ ;; TODO: Color lines based on which conspirator wrote them?
44
44
 
45
45
  ;;; Code:
46
46
 
47
- (defvar conspire-interval 0.33
47
+ (defcustom conspire-interval 0.25
48
48
  "Number of seconds to wait before syncing with conspire.")
49
49
 
50
+ (defcustom conspire-arguments ""
51
+ "Arguments to pass the `conspire' executable, like port, name, etc.")
52
+
50
53
  (defvar conspire-timer nil
51
54
  "A timer to activate conspire synchronizing.")
52
55
 
53
- (make-variable-buffer-local 'conspire-mode)
54
-
55
- ;;;###autoload
56
- (defun conspire-mode ()
57
- "Activate conspire-mode for real-time collaborative editing."
58
- (interactive)
59
- (setq conspire-mode t)
60
- (setq conspire-timer
61
- (run-with-idle-timer conspire-interval :repeat 'conspire-sync-buffer)))
62
-
63
-
64
56
  (defun conspire-sync-buffer ()
65
57
  "Synchronize buffer with Conspire repository."
66
58
  (when conspire-mode
@@ -68,8 +60,27 @@
68
60
  (save-buffer)
69
61
  (shell-command (format "git add %s && git commit -m \"conspire\""
70
62
  buffer-file-name)))
71
- (revert-buffer nil t)
72
- ;; revert resets local variables; heh
73
- (setq conspire-mode t)))
63
+ (revert-buffer nil t) ;; revert resets local variables; heh
64
+ (cancel-timer conspire-timer)
65
+ (conspire-mode t)))
66
+
67
+ ;;;###autoload
68
+ (define-minor-mode conspire-mode
69
+ "Toggle conspire-mode for real-time collaborative editing.
70
+
71
+ If the current buffer isn't part of a conspiracy session, a new
72
+ session will be started."
73
+ :lighter "-conspire"
74
+ (unless (file-exists-p (concat (file-name-directory buffer-file-name)
75
+ ".conspire"))
76
+ (save-window-excursion
77
+ (shell-command (format "conspire %s %s >& /dev/null &"
78
+ (file-name-directory buffer-file-name)
79
+ conspire-arguments))))
80
+ (setq conspire-timer
81
+ (or conspire-timer
82
+ (run-with-idle-timer conspire-interval :repeat
83
+ 'conspire-sync-buffer))))
74
84
 
85
+ (provide 'conspire)
75
86
  ;;; conspire.el ends here
@@ -25,12 +25,12 @@ class TestConspire < Test::Unit::TestCase
25
25
  def setup
26
26
  Gitjour::Application.init(REMOTE_SPACE)
27
27
  File.open(REMOTE_SPACE + '/file', 'w') { |f| f.puts "hello world." }
28
- `cd #{REMOTE_SPACE}; git add file; git commit -m "init"`
28
+ `cd #{REMOTE_SPACE}; git add file; git commit -m "conspire"`
29
29
 
30
30
  @remote_thread = Thread.new do
31
31
  Gitjour::Application.serve(REMOTE_SPACE, 'conspiracy-remote-test', 7458)
32
32
  end
33
-
33
+ @remote = Conspire::Conspirator.new('localhost.', '7458', 'conspiracy')
34
34
  Conspire.start(LOCAL_SPACE, OpenStruct.new(:port => 7457,
35
35
  :name => 'conspiracy',
36
36
  :sync_interval => 0.5))
@@ -55,14 +55,25 @@ class TestConspire < Test::Unit::TestCase
55
55
 
56
56
  def test_sync
57
57
  # getting random unreproducible failings here
58
- Conspire.conspirators << Conspire::Conspirator.new('localhost.', '7458')
58
+ Conspire.conspirators << @remote
59
59
  Conspire.sync_all
60
60
  assert_equal ["#{LOCAL_SPACE}/file"], Dir.glob("#{LOCAL_SPACE}/*")
61
61
  end
62
62
 
63
63
  def test_conspirator_set
64
- Conspire.conspirators << Conspire::Conspirator.new('dynabook.', '7458')
65
- Conspire.conspirators << Conspire::Conspirator.new('dynabook.', '7458')
64
+ Conspire.conspirators << Conspire::Conspirator.new('dynabook.', '7458', 'conspiracy')
65
+ Conspire.conspirators << Conspire::Conspirator.new('dynabook.', '7458', 'conspiracy')
66
66
  assert_equal 1, Conspire.conspirators.size
67
67
  end
68
+
69
+ def test_conflicts
70
+ @remote.sync(LOCAL_SPACE)
71
+ assert File.exist?(LOCAL_SPACE + '/file'), "Sync did not pull in file"
72
+ assert_equal 'hello world.\n', File.read(LOCAL_SPACE + '/file')
73
+
74
+ File.open("#{LOCAL_SPACE}/file", 'w') { |f| f.puts "hello conspirators!" }
75
+ `cd #{LOCAL_SPACE}; git add file; git commit -m "conspire"`
76
+ @remote.sync(LOCAL_SPACE)
77
+ assert_equal 'hello conspirators!\n', File.read(LOCAL_SPACE + '/file')
78
+ end
68
79
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: technomancy-conspire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Hagelberg
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-24 00:00:00 -07:00
12
+ date: 2008-08-12 00:00:00 -07:00
13
13
  default_executable: conspire
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: 6.3.0
23
23
  version:
24
24
  - !ruby/object:Gem::Dependency
25
- name: clip
25
+ name: alexvollmer-clip
26
26
  version_requirement:
27
27
  version_requirements: !ruby/object:Gem::Requirement
28
28
  requirements:
@@ -56,6 +56,7 @@ files:
56
56
  - README.rdoc
57
57
  - Rakefile
58
58
  - bin/conspire
59
+ - conspire.gemspec
59
60
  - lib/conspire.rb
60
61
  - lib/conspire/conspirator.rb
61
62
  - lib/conspire/gitjour_exts.rb
@@ -63,7 +64,7 @@ files:
63
64
  - test/perf.rb
64
65
  - test/test_conspire.rb
65
66
  has_rdoc: true
66
- homepage: http://conspire.rubyforge.org
67
+ homepage: http://github.com/technomancy/conspire
67
68
  post_install_message:
68
69
  rdoc_options:
69
70
  - --main