shagit 0.3.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/CHANGES ADDED
@@ -0,0 +1,29 @@
1
+ 0.3 (2010-03-17)
2
+ ==================================
3
+ * refactored global variables into a singleton class
4
+ * changed require statement inside config.ru to reflect recent name changes
5
+ * modified stylesheet
6
+ * exchanged OS call 'hostname' with request.env
7
+ * fixed repository location bug
8
+ * added rakefile
9
+ * added proper dependencies for production & development to gem
10
+ * added new test case to unit test (tests loading of the configuration file)
11
+ * added gem building using jeweler
12
+ * added runtime checking (to check if Shagit was installed using the gem)
13
+
14
+ 0.2 (2010-02-27)
15
+ ==================================
16
+ * fixed password input field
17
+ * implemented working_dir setting
18
+ * converted README to Markdown format
19
+ * moved helpers folder to lib
20
+ * added $LOAD_PATH statements
21
+ * renamed shagit.rb to shagit_app.rb due to name conflicts with lib/shagit.rb
22
+ * added acceptance tests using Webrat
23
+
24
+ 0.1 Initial Release (2010-01-11)
25
+ ==================================
26
+ * Basic create, optimize and delete functions implemented for repositories
27
+ * Authentication system implemented
28
+ * Integration of Integrity's CSS and layout
29
+ * Deployment via Phusion Passenger
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009, 2010 Martin Gajdos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ Shagit
2
+ ============
3
+
4
+ Description: A simple web application for local, private git repository management written in Sinatra
5
+ Copyright (c) 2009, 2010 Martin Gajdos
6
+
7
+ released under the MIT license
8
+
9
+ Introduction
10
+ ------------
11
+
12
+ Shagit is a simple web application for managing your local git repositories. There's no need for a database and repositories are being privately published using ssh.
13
+
14
+ Dependencies
15
+ ------------
16
+
17
+ * Sinatra
18
+ * Haml
19
+ * Grit
20
+ * Rack-Test
21
+ * Webrat
22
+
23
+ Installation
24
+ ------------
25
+
26
+ You will need a working installation of Ruby >=1.8.6, RubyGems >= 1.3.5 and Git >= 1.5
27
+
28
+ Clone the repository:
29
+
30
+ git clone git://github.com/unabatede/shagit.git
31
+
32
+ Install the Sinatra, Haml & Grit gems:
33
+
34
+ gem install sinatra haml grit rack-test webrat
35
+
36
+ Run it (you should consider other options for production deployment):
37
+
38
+ cd shagit
39
+ ruby shagit.rb -e production
40
+
41
+ Deployment
42
+ ----------
43
+
44
+ Using Apache & Phusion Passenger and the following to a new virtual host file (adjust to suite your needs):
45
+
46
+ <VirtualHost *:80>
47
+ DocumentRoot /var/www/shagit/public
48
+ <Directory /var/www/shagit/public>
49
+ Allow from all
50
+ Options -MultiViews
51
+ </Directory>
52
+ </VirtualHost>
53
+
54
+
55
+ Also, inside Shagit's folder, create a 'tmp' and 'public' folder:
56
+
57
+ cd /var/www/shagit
58
+ mkdir tmp; mkdir public
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 3
4
+ :patch: 0
5
+
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..')
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'rubygems'
6
+ require 'sinatra'
7
+ require 'shagit_app'
8
+
9
+ set :environment, :production
10
+
11
+ Sinatra::Application.run!
@@ -0,0 +1,3 @@
1
+ require 'shagit_app'
2
+
3
+ run Sinatra::Application
@@ -0,0 +1,6 @@
1
+ # provide credentials for the administrative user
2
+ username: admin
3
+ password: admin
4
+
5
+ # set path in which repositories are going to be created
6
+ working_dir:
@@ -0,0 +1,33 @@
1
+ module Sinatra
2
+ module Authorization
3
+
4
+ def authorize!(username, password)
5
+ # get the only instance of the Config class
6
+ config_data = ConfigInfo.instance
7
+
8
+ if (username == config_data.username) && (password == config_data.password)
9
+ session[:authorized] = true
10
+ true
11
+ else
12
+ session[:authorized] = false
13
+ false
14
+ end
15
+
16
+ end
17
+
18
+ def is_authorized?
19
+ if session[:authorized]
20
+ true
21
+ else
22
+ false
23
+ end
24
+ end
25
+
26
+ def requires_login!
27
+ if !is_authorized?
28
+ redirect '/login'
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ require 'singleton'
2
+
3
+ class ConfigInfo
4
+ include Singleton
5
+
6
+ attr :username, true
7
+ attr :password, true
8
+ attr :working_dir, true
9
+ end
@@ -0,0 +1,29 @@
1
+ # this adds a method called 'repo_name' that returns only the filename without path or file extension
2
+ require 'pathname'
3
+ require 'find'
4
+
5
+ module Grit
6
+ # return foldername including extension
7
+ def shagit_foldername
8
+ foldername = Pathname.new(self.path).basename.to_s
9
+ end
10
+
11
+ # return foldername from path without extension
12
+ def shagit_name
13
+ foldername = Pathname.new(self.shagit_foldername).basename.to_s
14
+
15
+ # extract repository name without .git extension
16
+ repo_name = foldername.match(/^[\w\s]+/).to_s
17
+ end
18
+
19
+ # return size of folder containing the repository in Kilobytes
20
+ def shagit_size
21
+ dirsize = 0
22
+ # recursively search the repositories path and sum up all file sizes
23
+ Find.find(self.path) do |file|
24
+ dirsize += File.stat(file).size
25
+ end
26
+
27
+ dirsize
28
+ end
29
+ end
@@ -0,0 +1,115 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "../"))
2
+
3
+ require 'authorization'
4
+ require 'pathname'
5
+ require 'config_info'
6
+
7
+ include Sinatra::Authorization
8
+
9
+ def stylesheets(*sheets)
10
+ sheets.each { |sheet|
11
+ haml_tag(:link, :href => "/#{sheet}.css", :type => "text/css", :rel => "stylesheet")
12
+ }
13
+ end
14
+
15
+ def cycle(*values)
16
+ @cycles ||= {}
17
+ @cycles[values] ||= -1 # first value returned is 0
18
+ next_value = @cycles[values] = (@cycles[values] + 1) % values.size
19
+ values[next_value]
20
+ end
21
+
22
+ def full_path
23
+ # get the only instance of the Config class
24
+ config_data = ConfigInfo.instance
25
+ #hostname = `hostname`
26
+ hostname = request.env['SERVER_NAME']
27
+ if (config_data.working_dir == '.')
28
+ full_path = "/#{@current_repo.shagit_foldername}"
29
+ else
30
+ full_path = "#{config_data.working_dir}/#{@current_repo.shagit_foldername}"
31
+ end
32
+
33
+ "ssh://#{reformat_string(hostname)}#{reformat_string(full_path)}"
34
+ end
35
+
36
+ def reformat_string(source)
37
+ source.strip
38
+ end
39
+
40
+ def get_config_file_dir(dir)
41
+ # check whether this is being called from a webrat test and if yes, adjust the calling path for the config_data file
42
+ if dir[/[\w]+$/] == "helpers"
43
+ dir = Pathname.new(File.expand_path(File.dirname(__FILE__)))
44
+ dir.parent.parent
45
+ else
46
+ dir
47
+ end
48
+ end
49
+
50
+ def load_config(file)
51
+ current_dir = File.expand_path(File.dirname(__FILE__))
52
+ absolute_filepath = File.join(get_config_file_dir(current_dir), file)
53
+
54
+ if File.exist?(absolute_filepath)
55
+ config_data = ConfigInfo.instance
56
+
57
+ yaml = YAML.load_file(absolute_filepath)
58
+ config_data.username = yaml['username']
59
+ config_data.password = yaml['password']
60
+
61
+ working_dir = yaml['working_dir']
62
+
63
+ # check whether working_dir has been specified
64
+ unless (working_dir == nil) || (working_dir.empty?)
65
+ working_dir = working_dir.strip
66
+ # check whether the specified folder exists, if not, set it to the directory Shagit's located at
67
+ if FileTest.directory?(working_dir)
68
+ config_data.working_dir = working_dir
69
+ else
70
+ set_working_dir_to_current_dir
71
+ end
72
+ else
73
+ set_working_dir_to_current_dir
74
+ end
75
+ end
76
+ end
77
+
78
+ def set_working_dir_to_current_dir
79
+ config_data = ConfigInfo.instance
80
+ config_data.working_dir = "."
81
+ end
82
+
83
+ def get_fullpath(path)
84
+ config_data = ConfigInfo.instance
85
+
86
+ # add the .git extension if it isn't there already
87
+ if !path.include?('.git')
88
+ path = "#{path}.git"
89
+ end
90
+
91
+ fullpath = "#{config_data.working_dir}/#{path}"
92
+ end
93
+
94
+ def check_if_started_from_gem(current_working_directory)
95
+ config_data = ConfigInfo.instance
96
+
97
+ # check if the bin folder is included in the directory this file is located in
98
+ if current_working_directory.include?('bin')
99
+ if (config_data.working_dir == '.')
100
+ puts "FATAL ERROR: The directory for saving repositories cannot be used!"
101
+ puts "Please set the path in your config.yml accordingly."
102
+ exit
103
+ end
104
+
105
+ # if so, we know Shagit has been installed via gem and the application's root folder has to be redirected
106
+ set :root, current_working_directory
107
+ end
108
+
109
+ # check if the working directory for saving repositories is writable
110
+ if !FileTest.writable_real?(config_data.working_dir)
111
+ puts "FATAL ERROR: The directory for saving repositories (#{config_data.working_dir}) is not writable!"
112
+ puts "Please adjust your config.yml accordingly."
113
+ exit
114
+ end
115
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'grit'
4
+ require 'config_info'
5
+ include Grit
6
+
7
+ # Main class for shagit, initializes and manages all repositories
8
+ class Shagit
9
+ attr_reader :repositories
10
+
11
+ # checks if a specified directory is a github repository
12
+ def self.is_it_a_git_repo?(path)
13
+ if FileTest.directory?(path) && FileTest.directory?("#{path}/hooks") && FileTest.directory?("#{path}/info") && FileTest.directory?("#{path}/objects") && FileTest.directory?("#{path}/refs")
14
+ true
15
+ else
16
+ false
17
+ end
18
+ end
19
+
20
+ # initialize shagit by looking for git repositories in specified path
21
+ def initialize
22
+ # get the only instance of the Config class
23
+ config_data = ConfigInfo.instance
24
+
25
+ @repositories = Array.new
26
+ Dir.foreach(config_data.working_dir) do |path|
27
+ fullpath = "#{config_data.working_dir}/#{path}"
28
+
29
+ if Shagit.is_it_a_git_repo?(fullpath)
30
+ puts "adding repository: #{fullpath}"
31
+ # create a new Grit repository object if a directory has been found that looks to be a folder containing a git repository
32
+ @repositories << Repo.new(fullpath) unless (path == '.git')
33
+ end
34
+ end
35
+ end
36
+
37
+ # creates a new bare repository for the specified path if it doesn't already exist
38
+ def self.create_repo(full_repo_name)
39
+ # if the repository already exists, simply return 'false'
40
+ if FileTest.directory?(full_repo_name)
41
+ false
42
+ else
43
+ puts "creating bare repository at: #{full_repo_name}"
44
+ #new_repo = Grit::Repo.init_bare(full_repo_name)
45
+ puts "pwd: #{Dir.pwd}"
46
+ new_repo = Grit::Repo.init_bare(full_repo_name)
47
+ end
48
+ end
49
+
50
+ # deletes an existing repository
51
+ def self.delete_repo!(full_repo_name)
52
+ if FileTest.directory?(full_repo_name)
53
+ FileUtils.rm_rf(full_repo_name)
54
+ true
55
+ else
56
+ false
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,82 @@
1
+ /* --------------------------------------------------------------
2
+
3
+ buttons.css
4
+ * Gives you some great CSS-only buttons.
5
+
6
+ Created by Kevin Hale [particletree.com]
7
+ * particletree.com/features/rediscovering-the-button-element
8
+
9
+ See Readme.txt in this folder for instructions.
10
+
11
+ -------------------------------------------------------------- */
12
+
13
+ button {
14
+ display:block;
15
+ float:left;
16
+ margin:0 0.583em 0.667em 0;
17
+ padding:5px 10px 5px 7px; /* Links */
18
+
19
+ border:1px solid #dedede;
20
+ border-top:1px solid #eee;
21
+ border-left:1px solid #eee;
22
+
23
+ background-color:#f5f5f5;
24
+ font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
25
+ font-size:100%;
26
+ line-height:130%;
27
+ text-decoration:none;
28
+ font-weight:bold;
29
+ color:#565656;
30
+ cursor:pointer;
31
+ }
32
+ button {
33
+ width:auto;
34
+ overflow:visible;
35
+ padding:4px 10px 3px 7px; /* IE6 */
36
+ }
37
+ button[type] {
38
+ padding:4px 10px 4px 7px; /* Firefox */
39
+ line-height:17px; /* Safari */
40
+ }
41
+ *:first-child+html button[type] {
42
+ padding:4px 10px 3px 7px; /* IE7 */
43
+ }
44
+ button img {
45
+ margin:0 3px -3px 0 !important;
46
+ padding:0;
47
+ border:none;
48
+ width:16px;
49
+ height:16px;
50
+ float:none;
51
+ }
52
+
53
+
54
+ /* Button colors
55
+ -------------------------------------------------------------- */
56
+
57
+ /* Standard */
58
+ button:hover {
59
+ background-color:#dff4ff;
60
+ border:1px solid #c2e1ef;
61
+ color:#336699;
62
+ }
63
+
64
+ /* Positive */
65
+ body .positive {
66
+ color:#529214;
67
+ }
68
+ button.positive:hover {
69
+ background-color:#E6EFC2;
70
+ border:1px solid #C6D880;
71
+ color:#529214;
72
+ }
73
+
74
+ /* Negative */
75
+ body .negative {
76
+ color:#d12f19;
77
+ }
78
+ button.negative:hover {
79
+ background:#fbe3e4;
80
+ border:1px solid #fbc2c4;
81
+ color:#d12f19;
82
+ }