├── Rakefile
├── lib
├── gaucho
│ ├── version.rb
│ ├── page.rb
│ ├── metadata.rb
│ ├── commit.rb
│ ├── index.rb
│ └── pageset.rb
└── gaucho.rb
├── .gitignore
├── Gemfile
├── README.md
├── spec
├── gaucho
│ ├── page_spec.rb
│ ├── metadata_spec.rb
│ ├── index_spec.rb
│ ├── commit_spec.rb
│ └── pageset_spec.rb
├── generate_fixtures.rb
└── fixtures_helper.rb
├── gaucho.gemspec
└── .rvmrc
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'bundler'
2 | Bundler::GemHelper.install_tasks
3 |
--------------------------------------------------------------------------------
/lib/gaucho/version.rb:
--------------------------------------------------------------------------------
1 | module Gaucho
2 | VERSION = "0.0.1"
3 | end
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | .bundle
3 | Gemfile.lock
4 | pkg/*
5 | spec/fixtures/*
6 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | # Specify your gem's dependencies in gaucho.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gaucho
2 |
3 | Ruby + Git + Content = Gaucho
4 |
5 | ## Copyright
6 |
7 | Copyright (c) 2011 "Cowboy" Ben Alman
8 | Dual licensed under the MIT and GPL licenses.
9 |
10 |
--------------------------------------------------------------------------------
/lib/gaucho.rb:
--------------------------------------------------------------------------------
1 | #require 'forwardable'
2 |
3 | require 'yaml'
4 |
5 | require 'grit'
6 | require 'pp'
7 |
8 | require 'gaucho/pageset'
9 | require 'gaucho/page'
10 | require 'gaucho/commit'
11 | require 'gaucho/metadata'
12 | require 'gaucho/index'
13 |
14 | module Gaucho
15 | # Your code goes here...
16 | end
17 |
--------------------------------------------------------------------------------
/lib/gaucho/page.rb:
--------------------------------------------------------------------------------
1 |
2 | module Gaucho
3 | class Page
4 | attr_reader :id, :pageset
5 |
6 | def initialize(id, pageset)
7 | @id = id
8 | @pageset = pageset
9 | end
10 |
11 | # A list of commits for this page.
12 | def commits
13 | return @commits unless @commits.nil?
14 | pc = pageset.page_commits[id]
15 | @commits = pc.collect {|obj| Gaucho::Commit.new obj[:sha], self}
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/gaucho/page_spec.rb:
--------------------------------------------------------------------------------
1 | require 'gaucho'
2 | require 'pp'
3 |
4 | module Gaucho
5 | describe Page do
6 | before do
7 | @pageset = Pageset.new 'spec/fixtures/basic'
8 | @page = Page.new 'page-1', @pageset
9 | end
10 |
11 | describe "#id" do
12 | it "should reflect the passed-in id" do
13 | page = Page.new 'SAMPLE', nil
14 | page.id.should eq 'SAMPLE'
15 | end
16 | end
17 |
18 | describe "#pageset" do
19 | it "should reflect the passed-in pageset" do
20 | @page.pageset.should eq @pageset
21 | end
22 | end
23 |
24 | describe "#commits" do
25 | it "should contain a list of Gaucho::Commit objects" do
26 | @page.commits.all? {|c| c.instance_of? Gaucho::Commit}.should eq true
27 | end
28 | end
29 | end
30 | end
--------------------------------------------------------------------------------
/lib/gaucho/metadata.rb:
--------------------------------------------------------------------------------
1 |
2 | # More friendly looking dot-syntax access for hash keys.
3 | # http://mjijackson.com/2010/02/flexible-ruby-config-objects
4 | module Gaucho
5 | class Metadata
6 | def initialize(data = {})
7 | @data = {}
8 | data.each {|key, value| self[key] = value}
9 | end
10 |
11 | def to_hash
12 | @data
13 | end
14 |
15 | def [](key)
16 | @data[key.downcase.to_sym]
17 | end
18 |
19 | def []=(key, value)
20 | @data[key.downcase.to_sym] = if value.instance_of? Hash
21 | self.class.new value
22 | else
23 | value
24 | end
25 | end
26 |
27 | def method_missing(method, *args)
28 | if method.to_s =~ /^(.+)=$/
29 | self[$1] = args.first
30 | else
31 | self[method]
32 | end
33 | end
34 | end
35 | end
--------------------------------------------------------------------------------
/gaucho.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | $:.push File.expand_path("../lib", __FILE__)
3 | require "gaucho/version"
4 |
5 | Gem::Specification.new do |s|
6 | s.name = "gaucho"
7 | s.version = Gaucho::VERSION
8 | s.platform = Gem::Platform::RUBY
9 | s.authors = ['"Cowboy" Ben Alman']
10 | s.email = ["TODO: Write your email address"]
11 | s.homepage = ""
12 | s.summary = %q{TODO: Write a gem summary}
13 | s.description = %q{TODO: Write a gem description}
14 |
15 | s.rubyforge_project = "gaucho"
16 |
17 | s.add_dependency "grit", "~> 2.4"
18 |
19 | s.add_development_dependency "rspec", "~> 2.6"
20 |
21 | s.files = `git ls-files`.split("\n")
22 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24 | s.require_paths = ["lib"]
25 | end
26 |
--------------------------------------------------------------------------------
/lib/gaucho/commit.rb:
--------------------------------------------------------------------------------
1 |
2 | module Gaucho
3 | class Commit
4 | extend Forwardable
5 |
6 | attr_reader :commit, :page
7 |
8 | # Forward Grit::Commit methods to :commit.
9 | def_delegators :commit, :id, :parents, :message, :author, :committer,
10 | :authored_date, :committed_date
11 |
12 | def initialize(commit_id, page)
13 | @page = page
14 | @commit = @page.pageset.repo.commit commit_id
15 | end
16 |
17 | # Grit::Tree for this page at this commit.
18 | def tree
19 | if page.pageset.subdir.nil?
20 | commit.tree/page.id
21 | else
22 | commit.tree/page.pageset.subdir/page.id
23 | end
24 | end
25 |
26 | # Metadata for this commit's page index.md file.
27 | def meta
28 | return @meta unless @meta.nil?
29 | index = tree.blobs.find {|blob| blob.name =~ /^index\./}
30 | @meta = parse_index index.name, index.data
31 | end
32 |
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/gaucho/index.rb:
--------------------------------------------------------------------------------
1 |
2 | module Gaucho
3 | class Index
4 | attr_reader :file_name, :meta
5 |
6 | def initialize(file_name, data)
7 | @file_name = file_name
8 | @data = data
9 | parse_data
10 | end
11 |
12 | private
13 |
14 | # Parse index file into metadata.
15 | def parse_data
16 | docs = []
17 | YAML.each_document(@data) {|doc| docs << doc}# rescue nil
18 | docs = [{}, @data] unless docs.length == 2
19 | docs.first.each do |key, value|
20 | docs.first[key] = value.collect {|e| e.to_s} if value.instance_of? Array
21 | end
22 | @meta = Gaucho::Metadata.new docs.first
23 |
24 | # meta.excerpt is anything before , meta.content is everything
25 | # before + everything after.
26 | parts = docs.last.split(/^\s*\s*$/im)
27 | @meta.excerpt = (parts[0] || '').chomp
28 | @meta.content = @meta.excerpt + (parts[1] || '').chomp
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/.rvmrc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This is an RVM Project .rvmrc file, used to automatically load the ruby
4 | # development environment upon cd'ing into the directory
5 |
6 | # First we specify our desired [@], the @gemset name is optional.
7 | environment_id="ruby-1.9.2-p180@gaucho"
8 |
9 | #
10 | # First we attempt to load the desired environment directly from the environment
11 | # file. This is very fast and efficicent compared to running through the entire
12 | # CLI and selector. If you want feedback on which environment was used then
13 | # insert the word 'use' after --create as this triggers verbose mode.
14 | #
15 | if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
16 | && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then
17 | \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
18 | else
19 | # If the environment file has not yet been created, use the RVM CLI to select.
20 | rvm --create "$environment_id"
21 | fi
22 |
23 | #
24 | # If you use an RVM gemset file to install a list of gems (*.gems), you can have
25 | # it be automatically loaded. Uncomment the following and adjust the filename if
26 | # necessary.
27 | #
28 | # filename=".gems"
29 | # if [[ -s "$filename" ]] ; then
30 | # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
31 | # fi
32 |
33 | #
34 | # If you use bundler and would like to run bundle each time you enter the
35 | # directory, you can uncomment the following code.
36 | #
37 | # # Ensure that Bundler is installed. Install it if it is not.
38 | # if ! command -v bundle >/dev/null; then
39 | # printf "The rubygem 'bundler' is not installed. Installing it now.\n"
40 | # gem install bundler
41 | # fi
42 | #
43 | # # Bundle while reducing excess noise.
44 | # printf "Bundling your gems. This may take a few minutes on a fresh clone.\n"
45 | # bundle | grep -v '^Using ' | grep -v ' is complete' | sed '/^$/d'
46 | #
47 |
48 |
--------------------------------------------------------------------------------
/spec/gaucho/metadata_spec.rb:
--------------------------------------------------------------------------------
1 | require 'gaucho'
2 |
3 | module Gaucho
4 | describe Metadata do
5 | describe "#to_hash" do
6 | it "should reflect the underlying hash" do
7 | hash = {a: 123}
8 | meta = Gaucho::Metadata.new hash
9 | meta.to_hash.should eq hash
10 | end
11 | end
12 |
13 | describe "#[]" do
14 | it "should access the underlying hash properties" do
15 | hash = {a: 123}
16 | meta = Gaucho::Metadata.new hash
17 | meta[:a].should eq hash[:a]
18 | end
19 | it "should be case insensitive" do
20 | meta = Gaucho::Metadata.new TeSt: 123
21 | meta[:tEsT].should eq 123
22 | end
23 | end
24 |
25 | describe "#[]=" do
26 | it "should set the underlying hash properties" do
27 | meta = Gaucho::Metadata.new
28 | meta[:a] = 123
29 | meta[:a].should eq 123
30 | end
31 | it "should work recursively" do
32 | meta = Gaucho::Metadata.new
33 | meta[:a] = {b: 1}
34 | meta[:a][:b].should eq 1
35 | meta[:a].instance_of?(Gaucho::Metadata).should eq true
36 | end
37 | end
38 |
39 | describe "#[arbitrary property]" do
40 | it "should work" do
41 | meta = Gaucho::Metadata.new a: 123
42 | meta.a.should eq 123
43 | end
44 | it "should work recursively" do
45 | meta = Gaucho::Metadata.new a: {b: 1}
46 | meta.a.b.should eq 1
47 | end
48 | it "should be case insensitive" do
49 | meta = Gaucho::Metadata.new TeSt: 123
50 | meta.tEsT.should eq 123
51 | end
52 | it "should allow setting" do
53 | meta = Gaucho::Metadata.new
54 | meta.a = 123
55 | meta.a.should eq 123
56 | end
57 | it "should allow setting recursively" do
58 | meta = Gaucho::Metadata.new
59 | meta.a = {b: 1}
60 | meta.a.b.should eq 1
61 | end
62 | end
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/spec/gaucho/index_spec.rb:
--------------------------------------------------------------------------------
1 | require 'gaucho'
2 |
3 | module Gaucho
4 | describe Index do
5 | describe "#file_name" do
6 | it "should reflect the passed-in file_name" do
7 | index = Gaucho::Index.new 'index.md', 'SAMPLE'
8 | index.file_name.should eq 'index.md'
9 | end
10 | end
11 |
12 | describe "#meta" do
13 | before do
14 | @excerpt = "This is an excerpt\nspread over two lines."
15 | @more = "And this is the rest\nof the content."
16 | @data_simple = @excerpt
17 | @data_more = "#{@excerpt}\n\n#{@more}"
18 | @data_yaml = <<-EOF.gsub(/^\s+/, '')
19 | Str1: A test string
20 | Str2: "Another test string"
21 | Array1: [foo, bar, baz]
22 | Array2: [1, 2, 3]
23 | --- |
24 | #{@data_more}
25 | EOF
26 | end
27 | it "should parse simple text data" do
28 | index = Gaucho::Index.new 'index.md', @data_simple
29 | index.meta.excerpt.should eq @excerpt
30 | index.meta.content.should eq @excerpt
31 | end
32 | it "should parse simple text data" do
33 | index = Gaucho::Index.new 'index.md', @data_more
34 | index.meta.excerpt.should eq @excerpt
35 | index.meta.content.should eq "#{@excerpt}\n#{@more}"
36 | end
37 | it "should parse yaml metadata + content" do
38 | index = Gaucho::Index.new 'index.md', @data_yaml
39 | index.meta.str1.should eq "A test string"
40 | index.meta.str2.should eq "Another test string"
41 | index.meta.array1.should eq %w{foo bar baz}
42 | index.meta.array2.should eq %w{1 2 3}
43 | index.meta.excerpt.should eq @excerpt
44 | index.meta.content.should eq "#{@excerpt}\n#{@more}"
45 | end
46 | it "should not care about --- before metadata" do
47 | index1 = Gaucho::Index.new 'index.md', @data_yaml
48 | index2 = Gaucho::Index.new 'index.md', "---\n#{@data_yaml}"
49 | index1.meta.to_hash.should eq index2.meta.to_hash
50 | end
51 | end
52 | end
53 | end
--------------------------------------------------------------------------------
/spec/generate_fixtures.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | require './fixtures_helper'
4 |
5 | # Pageset.new 'test' do |r|
6 | # r.write 'foo/bar.txt' => 'this is some sample content for foo'
7 | # r.write 'baz.txt' => 'this is some sample content for bar'
8 | # r.git_add_commit 'commit 1'
9 | #
10 | # r.append 'baz.txt' => 'bar has been modified!!!'
11 | # r.git_add_commit 'commit 2'
12 | # end
13 | #
14 | # Pageset.new 'two-pages' do |r|
15 | # r.page 'page-one' do |p|
16 | # p.meta 'Title' => 'Page One!', 'Tags' => %w{foo bar}
17 | # p.content 'this is sample page one'
18 | # r.git_add_commit 'page 1, commit 1'
19 | #
20 | # p.meta 'Title' => 'Page One Modified!', 'Tags' => %w{foo bar baz}
21 | # r.git_add_commit 'page 1, commit 2'
22 | # end
23 | #
24 | # r.page 'page-two' do |p|
25 | # p.meta 'Title' => 'Page Two!', 'Tags' => %w{bar baz}
26 | # p.content 'this is sample page two'
27 | # r.git_add_commit 'page 2, commit 1'
28 | #
29 | # p.content 'this is sample page two, modified!'
30 | # p.write 'foo.txt' => 'content for foo.txt'
31 | # r.git_add_commit 'page 2, commit 2'
32 | #
33 | # p.append 'foo.txt' => 'more content for foo.txt!'
34 | # r.git_add_commit 'page 2, commit 3'
35 | # end
36 | # end
37 |
38 | Pageset.new 'basic' do |r|
39 | 1.upto(3).each do |i|
40 | r.page "page-#{i}" do |p|
41 | p.meta 'Title' => "Page #{i}", 'Tags' => %w{foo bar baz}
42 | p.content "Sample content for page #{i}."
43 | r.git_add_commit "Created page #{i}."
44 | p.content "Modified content for page #{i}."
45 | p.write "file#{i}.txt" => "Sample file#{i} content"
46 | r.git_add_commit "Updated page #{i}."
47 | end
48 | end
49 | end
50 |
51 | Pageset.new 'subdir' do |r|
52 | %w{foo bar}.each do |subdir|
53 | 1.upto(2).each do |i|
54 | r.page "#{subdir}/#{subdir}-page-#{i}" do |p|
55 | p.meta 'Title' => "Page #{i}", 'Tags' => %w{foo bar baz}
56 | p.content "Sample content for #{subdir} page #{i}."
57 | r.git_add_commit "Created #{subdir} page #{i}."
58 | p.content "Modified content for #{subdir} page #{i}."
59 | p.write "file#{i}.txt" => "Sample file#{i} content"
60 | r.git_add_commit "Updated #{subdir} page #{i}."
61 | end
62 | end
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/lib/gaucho/pageset.rb:
--------------------------------------------------------------------------------
1 |
2 | module Gaucho
3 | class Pageset
4 | include Enumerable
5 |
6 | attr_reader :repo, :subdir
7 |
8 | def initialize(repo, options = {})
9 | # Init repo
10 | @repo = repo
11 | @repo = Grit::Repo.new(@repo) unless repo.instance_of? Grit::Repo
12 |
13 | # Initialize from options, overriding these defaults.
14 | { subdir: nil
15 | }.merge(options).each do |key, value|
16 | instance_variable_set "@#{key}".to_sym, value
17 | end
18 |
19 | # Ensure a specified subdir has a trailing slash.
20 | @subdir += '/' unless subdir.nil? || @subdir =~ %r{/$}
21 | end
22 |
23 | # Allow enumeration.
24 | def each
25 | if block_given? then
26 | pages.each {|page| yield page}
27 | else
28 | to_enum
29 | end
30 | end
31 |
32 | # Get a specific page by its id.
33 | def [](id)
34 | pages
35 | @pages_by_id[id]
36 | end
37 |
38 | # Get all pages.
39 | def pages
40 | return @pages unless @pages.nil?
41 |
42 | # Build pages.
43 | @pages = []
44 | @pages_by_id = {}
45 | page_commits.each do |id, commits|
46 | page = Gaucho::Page.new id, self
47 | @pages << page
48 | @pages_by_id[id] = page
49 | end
50 | @pages
51 | end
52 |
53 | # Get commit index for this repo. The git log is parsed manually, because
54 | # the structure Gaucho needs doesn't seem to exist anywhere in Grit.
55 | def page_commits
56 | return @page_commits unless @page_commits.nil?
57 |
58 | # Build page commit index.
59 | @page_commits = Hash.new {|h, k| h[k] = []}
60 |
61 | log = @repo.git.native(:log, {pretty: 'oneline', name_only: true,
62 | reverse: true, timeout: false})
63 |
64 | sha = nil
65 | log.split("\n").each do |line|
66 | if line =~ /^([0-9a-f]{40})/
67 | # Line is SHA, save for later.
68 | sha = $1
69 | elsif line =~ %r{^#{@subdir}(.*?)/(.*)}
70 | # Line is file path, push last seen SHA + file path onto this page's
71 | # array.
72 | pc = @page_commits[$1]
73 | # Create new object for this SHA, if necessary.
74 | pc << {sha: sha, files: []} if pc.empty? || sha != pc.last[:sha]
75 | # Push file onto this SHA's files array.
76 | pc.last[:files] << $2
77 | end
78 | end
79 | @page_commits
80 | end
81 | end
82 | end
83 |
--------------------------------------------------------------------------------
/spec/gaucho/commit_spec.rb:
--------------------------------------------------------------------------------
1 | require 'gaucho'
2 | require 'pp'
3 |
4 | module Gaucho
5 | describe Commit do
6 | before do
7 | @pageset = Pageset.new 'spec/fixtures/basic'
8 | @page = Page.new 'page-1', @pageset
9 |
10 | # Easiest way to get a valid commit SHA for this pageset.
11 | @id = @page.commits.last.id
12 | @commit = Gaucho::Commit.new @id, @page
13 | end
14 |
15 | describe "#id" do
16 | it "should reflect the passed-in id" do
17 | commit = Gaucho::Commit.new @id, @page
18 | commit.id.should eq @id
19 | end
20 | end
21 |
22 | describe "#commit" do
23 | it "should be a Grit::Commit object" do
24 | @commit.commit.instance_of?(Grit::Commit).should eq true
25 | end
26 |
27 | it "should be the correct Grit::Commit object" do
28 | @commit.commit.to_hash.should eq({
29 | "id"=>"56dfc6a4205432dfaba127fcbe1ae146c49d3748",
30 | "parents"=>[{"id"=>"a018c1844455aa6ee9d8b48fc6826e7d70963d74"}],
31 | "tree"=>"b15fe84ffee91f70cd2616cdacb4da9a9bae08ce",
32 | "message"=>"Updated page 1.",
33 | "author"=>{"name"=>"Ben Alman", "email"=>"cowboy@rj3.net"},
34 | "committer"=>{"name"=>"Ben Alman", "email"=>"cowboy@rj3.net"},
35 | "authored_date"=>"2000-01-03T09:00:00-08:00",
36 | "committed_date"=>"2000-01-04T09:00:00-08:00"
37 | })
38 | end
39 | end
40 |
41 | %w{id parents message author committer authored_date committed_date}.each do |method|
42 | describe "##{method}" do
43 | it "should foward to the underlying Grit::Commit object" do
44 | @commit.public_send(method.to_sym).should eq @commit.commit.public_send(method.to_sym)
45 | end
46 | end
47 | end
48 |
49 | describe "#tree" do
50 | it "should reflect the page's tree for this commit" do
51 | @commit.tree.contents.map(&:basename).should eq %w{file1.txt index.md}
52 | end
53 | it "should reflect the page's tree for this commit (w/subdir)" do
54 | pageset = Pageset.new 'spec/fixtures/subdir', subdir: 'foo'
55 | page = Page.new 'foo-page-1', pageset
56 | id = page.commits.last.id
57 | commit = Gaucho::Commit.new id, page
58 | commit.tree.contents.map(&:basename).should eq %w{file1.txt index.md}
59 | end
60 | end
61 |
62 | describe "#meta" do
63 | it "should reflect the commit's page metadata" do
64 | #pp @commit.meta
65 | end
66 | end
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/spec/gaucho/pageset_spec.rb:
--------------------------------------------------------------------------------
1 | require 'gaucho'
2 | require 'pp'
3 |
4 | module Gaucho
5 | describe Pageset do
6 | before do
7 | @pageset = Pageset.new 'spec/fixtures/basic'
8 | end
9 |
10 | describe "#repo" do
11 | it "should be a Grit::Repo (passing in a path)" do
12 | @pageset.repo.instance_of?(Grit::Repo).should eq true
13 | end
14 | it "should be a Grit::Repo (passing in a repo)" do
15 | repo = Grit::Repo.new 'spec/fixtures/basic'
16 | pageset = Pageset.new repo
17 | pageset.repo.instance_of?(Grit::Repo).should eq true
18 | end
19 | end
20 |
21 | describe "#subdir" do
22 | it "should be nil by default" do
23 | pageset = Pageset.new 'spec/fixtures/subdir'
24 | pageset.subdir.should eq nil
25 | end
26 | it "should reflect the passed-in subdir option" do
27 | pageset = Pageset.new 'spec/fixtures/subdir', subdir: 'foo/'
28 | pageset.subdir.should eq 'foo/'
29 | end
30 | it "should always have a trailing /" do
31 | pageset = Pageset.new 'spec/fixtures/subdir', subdir: 'foo'
32 | pageset.subdir.should eq 'foo/'
33 | end
34 | end
35 |
36 | # describe "#path" do
37 | # it "should be the path of the repo + the subdir" do
38 | # path = 'spec/fixtures/subdir'
39 | # subdir = 'foo'
40 | # dir = File.expand_path "#{path}/#{subdir}"
41 | # pageset = Pageset.new path, subdir: subdir
42 | # pageset.path.should eq dir
43 | # end
44 | # end
45 |
46 | describe "#page_commits" do
47 | # note: this is overly implementation-specific
48 | def make_test(page_id_regex)
49 | Proc.new do |id, commits|
50 | id =~ page_id_regex &&
51 | commits.count == 2 &&
52 | commits.first[:files].count == 1 &&
53 | commits.last[:files].count == 2
54 | end
55 | end
56 | it "should parse the commit log properly" do
57 | @pageset.page_commits.all?(&make_test(/^page-\d$/)).should eq true
58 | end
59 | it "should parse the commit log properly when subdir is used" do
60 | %w{foo bar}.each do |subdir|
61 | pageset = Pageset.new 'spec/fixtures/subdir', subdir: subdir
62 | pageset.page_commits.all?(&make_test(/^#{subdir}-page-\d$/)).should eq true
63 | end
64 | end
65 | end
66 |
67 | describe "#[]" do
68 | it "should allow access to pages by their id" do
69 | @pageset['page-1'].instance_of?(Gaucho::Page).should eq true
70 | @pageset['nonexistent'].should eq nil
71 | end
72 | end
73 |
74 | describe "#pages" do
75 | it "should allow access to all pages" do
76 | @pageset.pages.count.should eq 3
77 | @pageset.pages.all? {|page| page.instance_of? Gaucho::Page}.should eq true
78 | end
79 | end
80 |
81 | it "should behave like an Enumerable" do
82 | # Enumeration w/ block
83 | @pageset.inject(0) {|sum, page| sum += 1}.should eq 3
84 | # Enumerator w/o block
85 | @pageset.each.inject(0) {|sum, page| sum += 1}.should eq 3
86 | # Etc
87 | @pageset.count.should eq 3
88 | @pageset.first.instance_of?(Gaucho::Page).should eq true
89 | @pageset.all? {|page| page.instance_of? Gaucho::Page}.should eq true
90 | end
91 |
92 | #it "should default to sorting by commit date"
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/spec/fixtures_helper.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | require 'pp'
4 | require 'fileutils'
5 | require 'yaml'
6 |
7 | class Repo
8 | # create a new repo
9 | def initialize(repo_path)
10 | @time = Time.new(1999, 12, 31, 12, 0, 0, '-05:00')
11 | @repo_path = File.join 'fixtures', repo_path
12 | @pwd = FileUtils.pwd
13 | FileUtils.rm_rf @repo_path
14 | FileUtils.mkdir_p @repo_path
15 | FileUtils.cd @repo_path
16 | `git init .`
17 | yield self if block_given?
18 | done
19 | end
20 |
21 | # cleanup
22 | def done
23 | FileUtils.cd @pwd
24 | end
25 |
26 | # write some files
27 | def write(files = {}, mode = 'w')
28 | files.each do |path, content|
29 | FileUtils.mkdir_p(File.dirname path)
30 | File.open(path, mode) {|f| f.write content}
31 | end
32 | end
33 |
34 | # append to some files
35 | def append(files)
36 | write files, 'a'
37 | end
38 |
39 | # git add some files
40 | def git_add(files = ['.'])
41 | files.each {|file| `git add #{file}`}
42 | end
43 |
44 | # git commit with message
45 | def git_commit(message = 'bloops')
46 | # fake author / commit dates
47 | @time += 86400
48 | author_time = "#{@time.to_i} -0500"
49 | @time += 86400
50 | commit_time = "#{@time.to_i} -0500"
51 | `export GIT_AUTHOR_DATE="#{author_time}"; export GIT_COMMITTER_DATE="#{commit_time}"; git commit -m "#{message}"`
52 | end
53 |
54 | # git add + commit
55 | def git_add_commit(message = nil)
56 | git_add
57 | git_commit message
58 | end
59 | end
60 |
61 | class Pageset < Repo
62 | def page(page_name, &block)
63 | Page.new self, page_name, &block
64 | end
65 | end
66 |
67 | class Page
68 | def initialize(pageset, page_name)
69 | @pageset = pageset
70 | @page_name = page_name
71 | yield self if block_given?
72 | end
73 |
74 | # page index file
75 | def index_path
76 | File.join(@page_name, 'index.md')
77 | end
78 |
79 | # get/set metadata
80 | def meta(meta = nil)
81 | docs = read_index
82 | if !meta.nil?
83 | docs[0].merge! meta
84 | write_index docs
85 | end
86 | docs[0]
87 | end
88 |
89 | # get/set content
90 | def content(content = nil)
91 | docs = read_index
92 | if !content.nil?
93 | docs[1] = content
94 | write_index docs
95 | end
96 | docs[1]
97 | end
98 |
99 | # set content by appending
100 | def content_append(c = '')
101 | content(content + c)
102 | end
103 |
104 | # get all yaml docs from this page's index.md file
105 | def read_index
106 | docs = []
107 | if File.exists? index_path
108 | File.open(index_path) {|file| YAML.each_document(file) {|doc| docs << doc}}
109 | end
110 | docs[0] = {} if docs[0].nil?
111 | docs[1] = '' if docs[1].nil?
112 | docs
113 | end
114 |
115 | # write all yaml docs to this page's index.md file
116 | def write_index(docs)
117 | # Since this script tries to simulate how user data will actually be stored,
118 | # ie. without extra quoting or \\u-style escaping, and because .to_yaml escapes
119 | # unicode and quotes multi-line strings, YAML serialization is done manually.
120 | metas = []
121 | docs[0].each do |key, value|
122 | metas << if value.instance_of? Array
123 | "#{key}: [#{value.join(', ')}]"
124 | else
125 | "#{key}: #{value}"
126 | end
127 | end
128 | meta = if metas.empty?
129 | '---'
130 | else
131 | metas.join("\n")
132 | end
133 | @pageset.write index_path => "#{meta}\n--- |\n#{docs[1]}\n"
134 | end
135 |
136 | # write some files
137 | def write(files = {}, mode = 'w')
138 | f = {}
139 | files.each {|path, content| f[File.join @page_name, path] = content}
140 | @pageset.write f, mode
141 | end
142 |
143 | # append to some files
144 | def append(files)
145 | write files, 'a'
146 | end
147 | end
148 |
--------------------------------------------------------------------------------