cid 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 08cc9c8917f69e177896bea64e370d42af222bf7
4
+ data.tar.gz: 2a54b94ce968d84233d8f8de41883b214ca797a8
5
+ SHA512:
6
+ metadata.gz: a6ad26c203b9c356578ed153e8cf04182e4d230182e2d07158e8ab41d24a820e4da6409bdac389935a32ace32b31ff28bd6d29a85a0fe0a06c372a6bea0355ab
7
+ data.tar.gz: 3da71f338651e9086f3c7d6a2f2f9219b6f7a867a5c3859a4f2902072175355b479e21380e830a2a224dff9981099e27c808ac83b447cb54ad6ce35ab74d7a0d
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+
19
+ /.env
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ rvm:
2
+ - 2.0.0
3
+ notifications:
4
+ irc:
5
+ channels:
6
+ - irc.freenode.net#theodi
7
+ template:
8
+ - '%{repository} %{branch} - %{message} %{build_url}'
9
+ on_success: change
10
+ on_failure: always
11
+ env:
12
+ global:
13
+ secure: HZhBJjfU3C6ub01Ioong30m3NMAoT5re8XwDg3VQ86L2Z/lz/Zz7FU+cJvLcJJaO7Jj7UmZK0ov0kFxIesIJMV/KsMfmMOlJjTMz0K5g/C/NaTIKlZTY4Mg53oS4fh0ZNogtfkttOfL/JLyNS2buuSEuMtFtC0+DXlqklQ/JT3w=
data/Gemfile CHANGED
@@ -1,3 +1,6 @@
1
+ #ruby=ruby-2.0.0
2
+ #ruby-gemset=cid
3
+
1
4
  source 'https://rubygems.org'
2
5
 
3
6
  # Specify your gem's dependencies in cid.gemspec
data/Rakefile CHANGED
@@ -1 +1,17 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ $:.unshift File.join( File.dirname(__FILE__), "lib")
4
+
5
+ require 'rubygems'
6
+ require 'cucumber'
7
+ require 'cucumber/rake/task'
8
+ require 'coveralls/rake/task'
9
+ require 'rspec/core/rake_task'
10
+
11
+ RSpec::Core::RakeTask.new(:spec)
12
+ Coveralls::RakeTask.new
13
+ Cucumber::Rake::Task.new(:features) do |t|
14
+ t.cucumber_opts = "features --format pretty"
15
+ end
16
+
17
+ task :default => [:spec, :features, 'coveralls:push']
data/bin/cid CHANGED
@@ -48,4 +48,22 @@ if ARGV[0] == "validate"
48
48
 
49
49
  exit code
50
50
 
51
+ elsif ARGV[0] == "publish"
52
+
53
+ if ARGV[1]
54
+ source = ARGV[1]
55
+ else
56
+ source = "."
57
+ end
58
+
59
+ datapackage = Cid::Datapackage.new(source)
60
+ datapackage.create
61
+ datapackage.write
62
+ if File.exist?("#{source}/.git")
63
+ datapackage.publish
64
+ puts "Changes pushed successfully".colorize(:green)
65
+ else
66
+ puts "Git repo not found".colorize(:red)
67
+ exit 1
68
+ end
51
69
  end
data/cid.gemspec CHANGED
@@ -19,11 +19,22 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_dependency "csvlint"
21
21
  spec.add_dependency "colorize"
22
+ spec.add_dependency "json"
23
+ spec.add_dependency "git"
24
+ spec.add_dependency "github_api"
25
+ spec.add_dependency "dotenv"
26
+ spec.add_dependency "memoist"
22
27
 
23
28
  spec.add_development_dependency "bundler", "~> 1.3"
24
29
  spec.add_development_dependency "rake"
25
30
  spec.add_development_dependency "rspec"
26
31
  spec.add_development_dependency "pry"
32
+ spec.add_development_dependency "pry-remote"
27
33
  spec.add_development_dependency "coveralls"
34
+ spec.add_development_dependency "cucumber"
35
+ spec.add_development_dependency "aruba"
36
+ spec.add_development_dependency "spork"
37
+ spec.add_development_dependency "vcr"
38
+ spec.add_development_dependency "webmock"
28
39
 
29
40
  end
@@ -0,0 +1,29 @@
1
+ @publish
2
+ Feature: Publish a datapackage
3
+
4
+ Scenario: Create datapackage
5
+ Given I run `cp -r ../../spec/fixtures/valid valid`
6
+ And I cd to "valid"
7
+ When I run `cid publish`
8
+ And I run `cat datapackage.json`
9
+ Then the output should contain "votes/votes-1.csv"
10
+
11
+ Scenario: Create datapackage with new files
12
+ Given I run `cp -r ../../spec/fixtures/multiple_files multiple_files`
13
+ And I cd to "multiple_files"
14
+ When I run `cid publish`
15
+ And I run `cat datapackage.json`
16
+ Then the output should contain "votes/votes-1.csv"
17
+ And the output should contain "votes/votes-2.csv"
18
+
19
+ Scenario: Return error if not in a git repo
20
+ Given I run `cp -r ../../spec/fixtures/multiple_files multiple_files`
21
+ And I cd to "multiple_files"
22
+ When I run `cid publish`
23
+ Then the output should contain "Git repo not found"
24
+
25
+ Scenario: Sucessfully push to Github
26
+ Given I run `git clone https://github.com/theodi/cid-test.git`
27
+ And I cd to "cid-test"
28
+ When I successfully run `cid publish`
29
+ Then the output should contain "Changes pushed successfully"
@@ -0,0 +1,7 @@
1
+ Given(/^I set up a new git repo$/) do
2
+ steps %{
3
+ And I run `git init`
4
+ And I run `git add .`
5
+ And I run `git commit -am 'New git repo'`
6
+ }
7
+ end
@@ -0,0 +1,28 @@
1
+ $:.unshift File.join( File.dirname(__FILE__), "..", "..", "lib")
2
+
3
+ require 'rspec/expectations'
4
+ require 'pry'
5
+ require 'pry-remote'
6
+ require 'spork'
7
+ require 'aruba/cucumber'
8
+ require 'dotenv'
9
+
10
+ Dotenv.load
11
+
12
+ World(RSpec::Matchers)
13
+
14
+ Before do
15
+ @aruba_timeout_seconds = 10
16
+ end
17
+
18
+ Before('@validate') do
19
+ @dirs = ["#{File.dirname(__FILE__)}/../.."]
20
+ end
21
+
22
+ After('@publish') do
23
+ `rm -rf tmp/aruba/`
24
+ end
25
+
26
+ Spork.each_run do
27
+ require 'cid'
28
+ end
@@ -0,0 +1,30 @@
1
+ @validate
2
+ Feature: Validate a datapackage
3
+
4
+ Scenario: Package with a single CSV
5
+ When I cd to "spec/fixtures/valid"
6
+ And I run `cid validate`
7
+ Then the output should contain "votes/votes-1.csv is VALID"
8
+
9
+ Scenario: Package with multiple CSVs
10
+ When I cd to "spec/fixtures/multiple_files"
11
+ And I run `cid validate`
12
+ Then the output should contain "votes/votes-1.csv is VALID"
13
+ And the output should contain "votes/votes-2.csv is VALID"
14
+
15
+ Scenario: Package with multiple folders
16
+ When I cd to "spec/fixtures/multiple_folders"
17
+ And I run `cid validate`
18
+ Then the output should contain "seats/seats-1.csv is VALID"
19
+ And the output should contain "seats/seats-2.csv is VALID"
20
+ And the output should contain "votes/votes-1.csv is VALID"
21
+ And the output should contain "votes/votes-2.csv is VALID"
22
+
23
+ Scenario: Package with invalid CSV
24
+ When I cd to "spec/fixtures/invalid"
25
+ And I run `cid validate`
26
+ Then the output should contain "votes/votes-1.csv is INVALID"
27
+
28
+ Scenario: Specify directory
29
+ When I run `cid validate spec/fixtures/valid`
30
+ Then the output should contain "votes/votes-1.csv is VALID"
@@ -0,0 +1,57 @@
1
+ require 'csvlint'
2
+ require 'json'
3
+
4
+ module Cid
5
+
6
+ class Datapackage
7
+
8
+ attr_accessor :json
9
+
10
+ def initialize(path)
11
+ @path = path
12
+ begin
13
+ @datapackage = JSON.parse(File.new("#{@path}/datapackage.json").read)
14
+ rescue
15
+ return "No datapackage present!"
16
+ end
17
+ end
18
+
19
+ def create
20
+ # Clear out all the resources
21
+ @datapackage["resources"] = []
22
+
23
+ paths = Dir.glob("#{@path}/*/")
24
+
25
+ paths.each do |path|
26
+ schema = JSON.parse(File.new(Dir["#{path}/schema.json"][0]).read)
27
+
28
+ Dir["#{path}*.csv"].each do |csv|
29
+ @datapackage["resources"] << {
30
+ name: File.basename(csv, ".csv"),
31
+ path: csv.split("/").last(2).join("/"),
32
+ format: "csv",
33
+ mediatype: "text/csv",
34
+ bytes: File.size(csv),
35
+ schema: {
36
+ fields: schema["fields"]
37
+ }
38
+ }
39
+ end
40
+ end
41
+
42
+ @json = @datapackage.to_json
43
+ end
44
+
45
+ def write
46
+ self.create if @json.nil?
47
+ File.open("#{@path}/datapackage.json", 'w') { |f| f.write(@json) }
48
+ end
49
+
50
+ def publish
51
+ git = Cid::Publish.new(@path, ENV['GITHUB_OAUTH_TOKEN'])
52
+ git.publish
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,91 @@
1
+ require 'base64'
2
+ require 'github_api'
3
+ require 'memoist'
4
+
5
+ module Cid::Helpers::Github
6
+
7
+ extend Memoist
8
+
9
+ GITHUB_REPO_REGEX = /github.com[:\/]([^\/]*)\/([^\.]*)/
10
+
11
+ def github
12
+ Github.new oauth_token: @oauth_token
13
+ end
14
+ memoize :github
15
+
16
+ def user
17
+ match = @git_url.match GITHUB_REPO_REGEX
18
+ match ? match[1] : nil
19
+ end
20
+ memoize :user
21
+
22
+ def repo
23
+ match = @git_url.match GITHUB_REPO_REGEX
24
+ match ? match[2] : nil
25
+ end
26
+ memoize :repo
27
+
28
+ def default_branch
29
+ repository = github.repos.get user, repo
30
+ repository.default_branch
31
+ end
32
+ memoize :default_branch
33
+
34
+ def latest_commit(branch_name)
35
+ branch_data = github.repos.branch user, repo, branch_name
36
+ branch_data['commit']['sha']
37
+ end
38
+ memoize :latest_commit
39
+
40
+ def tree(branch)
41
+ github.git_data.trees.get user, repo, branch
42
+ end
43
+ memoize :tree
44
+
45
+ def blob_shas(branch, path)
46
+ tree = tree branch
47
+ Hash[tree['tree'].select{|x| x['path'] =~ /^#{path}$/ && x['type'] == 'blob'}.map{|x| [x.path, x.sha]}]
48
+ end
49
+ memoize :blob_shas
50
+
51
+ def blob_content(sha)
52
+ blob = github.git_data.blobs.get user, repo, sha
53
+ if blob['encoding'] == 'base64'
54
+ Base64.decode64(blob['content'])
55
+ else
56
+ blob['content']
57
+ end
58
+ end
59
+ memoize :blob_content
60
+
61
+
62
+ def create_blob(content)
63
+ blob = github.git_data.blobs.create user, repo, "content" => content, "encoding" => "utf-8"
64
+ blob['sha']
65
+ end
66
+
67
+ def add_blob_to_tree(sha, filename)
68
+ tree = tree default_branch
69
+ new_tree = github.git_data.trees.create user, repo, "base_tree" => tree['sha'], "tree" => [
70
+ "path" => filename,
71
+ "mode" => "100644",
72
+ "type" => "blob",
73
+ "sha" => sha
74
+ ]
75
+ new_tree['sha']
76
+ end
77
+
78
+ def commit(sha)
79
+ parent = latest_commit(default_branch)
80
+ commit = github.git_data.commits.create user, repo, "message" => "Updated datapackage.json",
81
+ "parents" => [parent],
82
+ "tree" => sha
83
+ commit['sha']
84
+ end
85
+
86
+ def push(sha)
87
+ branch = github.git_data.references.update user, repo, "heads/#{default_branch}", "sha" => sha
88
+ branch['ref']
89
+ end
90
+
91
+ end
@@ -0,0 +1,28 @@
1
+ require 'git'
2
+
3
+ module Cid
4
+
5
+ class Publish
6
+
7
+ include Cid::Helpers::Github
8
+
9
+ GITHUB_REPO_REGEX = /github.com[:\/]([^\/]*)\/([^\.]*)/
10
+
11
+ def initialize(path, oauth_token)
12
+ g = Git.open(path)
13
+ @path = path
14
+ @git_url = g.config["remote.origin.url"]
15
+ @oauth_token = oauth_token
16
+ end
17
+
18
+ def publish
19
+ name, content = "datapackage.json", File.read("#{@path}/datapackage.json")
20
+ blob_sha = create_blob(content)
21
+ tree_sha = add_blob_to_tree(blob_sha, name)
22
+ commit_sha = commit(tree_sha)
23
+ push(commit_sha)
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -13,7 +13,7 @@ module Cid
13
13
  begin
14
14
  schema = Csvlint::Schema.load_from_json_table(File.new(Dir["#{path}/schema.json"][0]))
15
15
  rescue
16
- # Error! No schema in place!
16
+ schema = nil
17
17
  end
18
18
 
19
19
  Dir["#{path}/*.csv"].each do |csv|
data/lib/cid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Cid
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/cid.rb CHANGED
@@ -1,2 +1,13 @@
1
+ module Cid
2
+
3
+ module Helpers
4
+ end
5
+
6
+ end
7
+
8
+ require "cid/helpers/github"
9
+
1
10
  require "cid/version"
2
11
  require "cid/validation"
12
+ require "cid/datapackage"
13
+ require "cid/publish"
@@ -0,0 +1,81 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.github.com/repos/theodi/cid-test/git/blobs?access_token=<GITHUB_OAUTH_TOKEN>
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"content":"new blob content","encoding":"utf-8"}'
9
+ headers:
10
+ Accept:
11
+ - application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
12
+ Accept-Charset:
13
+ - utf-8
14
+ User-Agent:
15
+ - Github Ruby Gem 0.11.3
16
+ Content-Type:
17
+ - application/json
18
+ Authorization:
19
+ - Token token="<GITHUB_OAUTH_TOKEN>"
20
+ Accept-Encoding:
21
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
22
+ response:
23
+ status:
24
+ code: 201
25
+ message: Created
26
+ headers:
27
+ Server:
28
+ - GitHub.com
29
+ Date:
30
+ - Thu, 22 May 2014 14:09:04 GMT
31
+ Content-Type:
32
+ - application/json; charset=utf-8
33
+ Status:
34
+ - 201 Created
35
+ X-Ratelimit-Limit:
36
+ - '5000'
37
+ X-Ratelimit-Remaining:
38
+ - '4998'
39
+ X-Ratelimit-Reset:
40
+ - '1400771341'
41
+ Cache-Control:
42
+ - private, max-age=60, s-maxage=60
43
+ Etag:
44
+ - '"3cb71254860221b3fe02e4d6afd3b069"'
45
+ X-Oauth-Scopes:
46
+ - gist, repo, user
47
+ X-Accepted-Oauth-Scopes:
48
+ - ''
49
+ Location:
50
+ - https://api.github.com/repos/theodi/cid-test/git/blobs/28b552e7359c5c3bbe947749aab70d18e3ea554b
51
+ Vary:
52
+ - Accept, Authorization, Cookie, X-GitHub-OTP
53
+ X-Github-Media-Type:
54
+ - github.v3; format=json
55
+ X-Xss-Protection:
56
+ - 1; mode=block
57
+ X-Frame-Options:
58
+ - deny
59
+ Content-Security-Policy:
60
+ - default-src 'none'
61
+ Content-Length:
62
+ - '154'
63
+ Access-Control-Allow-Credentials:
64
+ - 'true'
65
+ Access-Control-Expose-Headers:
66
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
67
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
68
+ Access-Control-Allow-Origin:
69
+ - '*'
70
+ X-Github-Request-Id:
71
+ - 4F4C59B3:0FE8:383DBFF:537E0500
72
+ Strict-Transport-Security:
73
+ - max-age=31536000
74
+ X-Content-Type-Options:
75
+ - nosniff
76
+ body:
77
+ encoding: UTF-8
78
+ string: '{"sha":"28b552e7359c5c3bbe947749aab70d18e3ea554b","url":"https://api.github.com/repos/theodi/cid-test/git/blobs/28b552e7359c5c3bbe947749aab70d18e3ea554b"}'
79
+ http_version:
80
+ recorded_at: Thu, 22 May 2014 14:09:09 GMT
81
+ recorded_with: VCR 2.4.0