shagit 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }