homedir 3.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ *~
5
+ /.bundle
6
+ /.config
7
+ /.yardoc
8
+ /.rvmrc
9
+ /Gemfile.lock
10
+ /doc/
11
+ /pkg/
12
+ /spec/reports
13
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - jruby
3
+ - 1.8.7
4
+ - 1.9.2
5
+ script: "bundle exec rake travis"
6
+ notifications:
7
+ irc: "irc.freenode.org#homedir"
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,17 @@
1
+ # Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'bundler' do
5
+ watch('Gemfile')
6
+ # Uncomment next line if Gemfile contain `gemspec' command
7
+ # watch(/^.+\.gemspec/)
8
+ end
9
+
10
+ guard 'rspec', :version => 2, :cli => "--color --format doc" do
11
+ watch(%r{^spec/.+_spec\.rb$})
12
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
+ watch('spec/spec_helper.rb') { "spec" }
14
+ watch('spec/factories.rb') { "spec" }
15
+ end
16
+
17
+
data/README.mkd ADDED
@@ -0,0 +1,100 @@
1
+ # HomeDir
2
+
3
+ *Manage your home directory!*
4
+
5
+ [![Build Status](https://secure.travis-ci.org/docwhat/homedir.png)](http://travis-ci.org/docwhat/homedir)
6
+
7
+ ## What is homedir?
8
+
9
+ HomeDir is a package manager for your home directory.
10
+
11
+ You can use other peoples HomeDir repositories or create your own!
12
+
13
+ ## Requirements
14
+
15
+ * Ruby (1.8.7 or newer) or JRuby (1.6.0)
16
+
17
+ ## Quick Start
18
+
19
+ gem install homedir
20
+
21
+ That's it!
22
+
23
+ ## Support
24
+
25
+ You can find me on freenode's IRC servers as the user 'docwhat'. I'm usually on the #homedir channel.
26
+
27
+ ## The Story So Far…
28
+
29
+ Since about 1999 I've been keeping my home directory config files in
30
+ [CVS](http://www.nongnu.org/cvs/). As the number of config files I've
31
+ been storing has grown and as the number of different systems I use it
32
+ on (my work desktop, my home desktop, my laptop, Gerf, my pda)
33
+ increases. As the complexity has grown it has become harder to
34
+ maintain.
35
+
36
+ So, I started looking around for a better solution. I noticed that
37
+ [SVN](http://subversion.tigris.org/) is a much better version control
38
+ system. I was already familiar with
39
+ [stow](http://www.gnu.org/software/stow/stow.html) as well. So I
40
+ tinkered around with combining them.
41
+
42
+ And thus homedir was born!
43
+
44
+ Since then, I rewrote HomeDir completely in python. This gives me more
45
+ control over the help and error messages. I can do better when
46
+ conflicts arrive. As well as I can add an elementry package format,
47
+ which allows me to solve the problem that uninstalling a stow package
48
+ can take forever if you have a lot of directories in your home.
49
+
50
+ A [friend](http://willnorris.com/) pointed out that the most important
51
+ part was the package manager. The various .dotfiles are interesting
52
+ to look at, but most people have their own. So I moved just the
53
+ package manager portion to [github](http://github.com/)
54
+
55
+ ## Migrating from older versions of homedir
56
+
57
+ ### 2.x
58
+
59
+ I'm working on the migration stuff.
60
+
61
+ ### 1.x
62
+
63
+ If you've using the pre-2.0 version of HomeDir (hosted on trac.gerf.org) then you should back up your .homedir directory before running the above `setup.py` script.
64
+
65
+ The main change is that everything in `~/.homedir/files` has been moved to `~/.homedir/packages` and the packages will no longer be automatically updated.
66
+
67
+ ## Change Log
68
+
69
+ ## 3.x
70
+
71
+ * Rewrite in Ruby
72
+ * Tons of unit tests
73
+
74
+ ## 2.x
75
+
76
+ * Broke out the code to be easier to debug and work with.
77
+ * Started adding tests.
78
+ * Suggestions on package management from Will Norris.
79
+
80
+ ## 1.x
81
+
82
+ The original HomeDir, which was hosted on trac.gerf.org, is going to be considered version 1.
83
+
84
+ Version 1 had a configuration file that kept track of where your packages were located.
85
+
86
+ In this new version packages can be placed anyplace under the directory
87
+ `~/.homedir/packages` (except inside another package, of course).
88
+
89
+ This allows for more flexability for managing packages.
90
+
91
+ This also means that sync/synccmd is no longer supported.
92
+
93
+ ## Similar Ideas
94
+
95
+ * I have also noticed that [Joey Hess](http://www.kitenet.net/~joey) has
96
+ also done something similar and written two articles about it:
97
+ * [CVS homedir, or keeping your life in CVS](http://kitenet.net/~joey/cvshome.html)
98
+ * [Subversion Users: home directory in svn?](http://www.kitenet.net/~joey/svnhome.html)
99
+ * [Homebrew](http://mxcl.github.com/homebrew/) does a lot of similar things, but for the system.
100
+ * The software package 'stow' also does similar symlinking for package installation. The original algorithm for directories was taken from there.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run all specs"
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ end
9
+ task :default => :spec
10
+
11
+ desc "Travis-CI Tests"
12
+ task :travis do
13
+ Rake::Task["spec"].invoke
14
+ end
data/homedir.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/homedir/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Christian Holtje"]
6
+ gem.email = ["docwhat@gerf.org"]
7
+ gem.description = %q{Your home directory package management system}
8
+ gem.summary = %q{Manage your home manager}
9
+ gem.homepage = "http://home-dir.org/"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "homedir"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Homedir::VERSION
17
+
18
+ gem.add_development_dependency('rake')
19
+ gem.add_development_dependency('rspec', ["~> 2.8"])
20
+ gem.add_development_dependency('fakefs', ["~> 0.4.0"])
21
+ gem.add_development_dependency('factory_girl', ["~> 2.5.2"])
22
+
23
+ gem.add_development_dependency('guard')
24
+ gem.add_development_dependency('guard-rspec')
25
+ gem.add_development_dependency('guard-bundler')
26
+ gem.add_development_dependency('rb-fsevent')
27
+ gem.add_development_dependency('growl')
28
+ end
@@ -0,0 +1,67 @@
1
+ require 'homedir'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ require 'yaml'
5
+
6
+ module Homedir
7
+ class Package
8
+ REQUIRED_OPTIONS = [
9
+ :name,
10
+ :description,
11
+ :directory,
12
+ ].freeze
13
+ DEFAULT_OPTIONS = {
14
+ :name => nil,
15
+ :description => nil,
16
+ :dependencies => [],
17
+ :post_install => nil,
18
+ :pre_install => nil,
19
+ :directory => nil,
20
+ }.freeze
21
+ attr_accessor *DEFAULT_OPTIONS.keys
22
+
23
+
24
+ def initialize(options = {})
25
+ options = DEFAULT_OPTIONS.merge(options)
26
+
27
+ # Set the options
28
+ options.each do |k,v|
29
+ send("#{k}=", v)
30
+ end
31
+ end
32
+
33
+ def dependencies= value
34
+ @dependencies = value.map { |p| p.to_s }
35
+ end
36
+
37
+ def directory= value
38
+ @directory = value.nil? ? nil : Pathname.new(value)
39
+ end
40
+
41
+ def name= value
42
+ raise "Invalid name: #{value.inspect}" unless value.nil? || value =~ /^[0-9a-zA-Z_-]+$/
43
+ @name = value
44
+ end
45
+
46
+ def save!
47
+ raise "The package is not valid: #{self}" unless valid?
48
+
49
+ control_dir = directory + '.homedir'
50
+ FileUtils.mkdir_p(control_dir.to_s) unless control_dir.directory?
51
+
52
+ (control_dir + "control").open('w') do |f|
53
+ f.write self.to_yaml
54
+ end
55
+ end
56
+
57
+ def valid?
58
+ REQUIRED_OPTIONS.reduce(true) do |is_valid, opt|
59
+ is_valid && !instance_variable_get("@#{opt}").nil?
60
+ end
61
+ end
62
+
63
+ def to_s
64
+ @name
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,27 @@
1
+ require 'pathname'
2
+ require 'homedir/package'
3
+
4
+ class Homedir::Repository
5
+ attr_reader :directory, :package_loader, :packages, :name
6
+
7
+ def initialize(directory, options={})
8
+ options = {
9
+ :package_loader => Homedir::Package,
10
+ }.merge(options)
11
+ @directory = Pathname.new(directory)
12
+ @name = @directory.basename.to_s
13
+ @package_loader = options[:package_loader]
14
+ end
15
+
16
+ def scan
17
+ packages = []
18
+ directory.each_entry do |entry|
19
+ next if entry.to_s.start_with? '.'
20
+ path = directory + entry
21
+ packages << package_loader.load_directory(path)
22
+ end
23
+ @packages = packages.freeze
24
+ return @packages
25
+ end
26
+
27
+ end
@@ -0,0 +1,4 @@
1
+
2
+ module Homedir
3
+ VERSION = '3.0.alpha1'
4
+ end
data/lib/homedir.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'homedir/package'
2
+
3
+ module Homedir
4
+ class Error < StandardError
5
+ end
6
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'homedir'
2
+
3
+ FactoryGirl.define do
4
+ factory :package, :class => Homedir::Package do
5
+ sequence(:name) { |n| "package-name-#{n}"}
6
+ sequence(:description) { |n| "package description #{n}" }
7
+ directory { File.join("test-directory", "#{name}") }
8
+ end
9
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'homedir/package'
3
+ require 'pathname'
4
+
5
+ describe Homedir::Package do
6
+
7
+ context "loading a v3 package from disk" do
8
+ describe "#read_from_directory"
9
+ end
10
+
11
+ describe "#new" do
12
+ context "creating a package from scratch" do
13
+ describe "dependencies" do
14
+ it "should accept all strings" do
15
+ package = build(:package, :dependencies => ['another_package'])
16
+ package.dependencies.size.should == 1
17
+ package.dependencies[0].should == 'another_package'
18
+ end
19
+ it "should accept packages" do
20
+ another_package = build(:package)
21
+ package = build(:package, :dependencies => [another_package])
22
+ package.dependencies.size.should == 1
23
+ package.dependencies[0].should == another_package.name
24
+ end
25
+ end
26
+
27
+ it "should set .name" do
28
+ name = "a-name"
29
+ build(:package, :name => name).name.should == name
30
+ end
31
+
32
+ it "should set .description" do
33
+ desc = "some words"
34
+ build(:package, :description => desc).description.should == desc
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#from_directory" do
40
+ it "should read its configuration from a directory"
41
+ end
42
+
43
+ describe ".name" do
44
+ it "should not accept an invalid name" do
45
+ pkg = build(:package)
46
+ expect { pkg.name = "a name" }.to raise_error
47
+ end
48
+ end
49
+
50
+ describe ".valid?" do
51
+ it "should require a name" do
52
+ build(:package, :name => nil).should_not be_valid
53
+ end
54
+
55
+ it "should require a description" do
56
+ build(:package, :description => nil).should_not be_valid
57
+ end
58
+ end
59
+
60
+ describe ".directory" do
61
+ it "should be a Pathname object" do
62
+ build(:package).directory.should be_an_instance_of(Pathname)
63
+ end
64
+ end
65
+
66
+ describe ".save!" do
67
+ it "should refuse to save if invalid" do
68
+ pkg = build(:package, :name => nil)
69
+ expect { pkg.save! }.to raise_error
70
+ end
71
+
72
+ it "should refuse to save if directory isn't set" do
73
+ pkg = build(:package, :directory => nil)
74
+ expect { pkg.save! }.to raise_error
75
+ end
76
+
77
+ it "should save files to '.homedir'" do
78
+ pkg = create(:package)
79
+ dot_homedir = Pathname.new(pkg.directory) + '.homedir'
80
+ dot_homedir.should be_a_directory
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'homedir/repository'
3
+ require 'pathname'
4
+
5
+ describe Homedir::Repository do
6
+ subject { Homedir::Repository.new directory, :package_loader => package_loader }
7
+ let(:package_loader) do
8
+ double().tap do |pl|
9
+ # :package is a placeholder for a Package instance
10
+ pl.stub(:load_directory) { :package }
11
+ end
12
+ end
13
+ let(:directory) { Pathname.new('/') } # an absolute directory
14
+ let(:package_dirs) { (1..10).map { |n| directory + "package-#{n}" } }
15
+
16
+ before(:each) do
17
+ # We need to make the directories exist so it can be scaned
18
+ package_dirs.each { |p| p.mkdir }
19
+ end
20
+
21
+ describe "#new" do
22
+ subject { Homedir::Repository }
23
+
24
+ it "should take a directory name" do
25
+ subject.new directory.to_s
26
+ end
27
+
28
+ it "should accept a pathname object" do
29
+ subject.new directory
30
+ end
31
+
32
+ it "should accept a Package class" do
33
+ subject.new directory, :package_loader => double()
34
+ end
35
+ end
36
+
37
+ describe ".scan" do
38
+ it "should load each package" do
39
+ package_dirs.each do |p|
40
+ package_loader.should_receive(:load_directory).with(p)
41
+ end
42
+ subject.scan.size.should == package_dirs.size
43
+ end
44
+ end
45
+
46
+ describe ".packages" do
47
+ it "should contain package objects" do
48
+ subject.scan
49
+ subject.packages.each do |p|
50
+ p.should == :package
51
+ end
52
+ end
53
+ end
54
+
55
+ describe ".name" do
56
+ it "should return the basename of the directory" do
57
+ repo = Homedir::Repository.new Pathname.new('/a/b/my-name')
58
+ repo.name.should == 'my-name'
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,12 @@
1
+ require 'fakefs'
2
+ require 'fakefs/spec_helpers'
3
+ require 'factory_girl'
4
+ require 'factories'
5
+
6
+ RSpec.configure do |config|
7
+ # Allows using build(), create(), etc. without the "FactoryGirl." part.
8
+ config.include FactoryGirl::Syntax::Methods
9
+
10
+ # resets the fake filesystem after each example
11
+ config.include FakeFS::SpecHelpers
12
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: homedir
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.alpha1
5
+ prerelease: 4
6
+ platform: ruby
7
+ authors:
8
+ - Christian Holtje
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-16 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70278115028520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70278115028520
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70278115027880 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.8'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70278115027880
36
+ - !ruby/object:Gem::Dependency
37
+ name: fakefs
38
+ requirement: &70278115024500 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.4.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70278115024500
47
+ - !ruby/object:Gem::Dependency
48
+ name: factory_girl
49
+ requirement: &70278115023820 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.2
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70278115023820
58
+ - !ruby/object:Gem::Dependency
59
+ name: guard
60
+ requirement: &70278115023440 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70278115023440
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: &70278115022940 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70278115022940
80
+ - !ruby/object:Gem::Dependency
81
+ name: guard-bundler
82
+ requirement: &70278115022440 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70278115022440
91
+ - !ruby/object:Gem::Dependency
92
+ name: rb-fsevent
93
+ requirement: &70278115022020 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70278115022020
102
+ - !ruby/object:Gem::Dependency
103
+ name: growl
104
+ requirement: &70278115021580 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70278115021580
113
+ description: Your home directory package management system
114
+ email:
115
+ - docwhat@gerf.org
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .gitignore
121
+ - .travis.yml
122
+ - Gemfile
123
+ - Guardfile
124
+ - README.mkd
125
+ - Rakefile
126
+ - homedir.gemspec
127
+ - lib/homedir.rb
128
+ - lib/homedir/package.rb
129
+ - lib/homedir/repository.rb
130
+ - lib/homedir/version.rb
131
+ - spec/factories.rb
132
+ - spec/lib/homedir/package_spec.rb
133
+ - spec/lib/homedir/repository_spec.rb
134
+ - spec/spec_helper.rb
135
+ homepage: http://home-dir.org/
136
+ licenses: []
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ segments:
148
+ - 0
149
+ hash: -3141288371879137994
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ! '>'
154
+ - !ruby/object:Gem::Version
155
+ version: 1.3.1
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 1.8.16
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: Manage your home manager
162
+ test_files:
163
+ - spec/factories.rb
164
+ - spec/lib/homedir/package_spec.rb
165
+ - spec/lib/homedir/repository_spec.rb
166
+ - spec/spec_helper.rb