Skip to content

Commit

Permalink
Publish release
Browse files Browse the repository at this point in the history
  • Loading branch information
alberthier committed Mar 18, 2016
1 parent 5e7879e commit 908132b
Show file tree
Hide file tree
Showing 5 changed files with 351 additions and 66 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "git-webui",
"version": "0.1.0",
"version": "1.1.0",
"authors": [
"Éric ALBER <[email protected]>"
],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "git-webui",
"version": "1.0.0",
"version": "1.1.0",
"description": "A web user interface for git",
"main": "index.js",
"scripts": {
Expand Down
121 changes: 58 additions & 63 deletions release/libexec/git-core/git-webui
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ import sys
import webbrowser

if sys.version > '3':
from http.server import CGIHTTPRequestHandler, HTTPServer
from urllib.parse import unquote
from http.server import SimpleHTTPRequestHandler, HTTPServer
from urllib.parse import unquote, urlparse
else:
from CGIHTTPServer import CGIHTTPRequestHandler
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer
from urllib import unquote
from urlparse import urlparse



Expand All @@ -41,25 +42,13 @@ IS_WINDOWS = platform.system() == "Windows"

allowed_hosts = ["127.0.0.1", "localhost"]

def which(cmd, path):
if IS_WINDOWS:
cmd += ".exe"
for d in path:
f = os.path.join(d, cmd)
if os.path.exists(f) and os.access(f, os.F_OK | os.X_OK):
return f
return None




class WebUiRequestHandler(CGIHTTPRequestHandler):

cgi_directories = []
class WebUiRequestHandler(SimpleHTTPRequestHandler):

WEB_ROOT = None
REPO_ROOT = None
GIT_HTTP_BACKEND_DIR = None

@classmethod
def initialize(cls, repo_root):
Expand All @@ -68,18 +57,6 @@ class WebUiRequestHandler(CGIHTTPRequestHandler):
WebUiRequestHandler.WEB_ROOT = web_root
WebUiRequestHandler.REPO_ROOT = repo_root

path = os.environ.get("PATH", os.defpath).split(os.pathsep)
git_http_backend = which("git-http-backend", path)
if git_http_backend is None:
git_prefix = os.path.dirname(os.path.dirname(which("git", path)))
candidates = [ os.path.join(git_prefix, "libexec", "git-core"),
os.path.join(git_prefix, "lib", "git-core") ]
git_http_backend = which("git-http-backend", candidates)
if git_http_backend is not None:
WebUiRequestHandler.GIT_HTTP_BACKEND_DIR = os.path.dirname(git_http_backend)
os.environ["GIT_PROJECT_ROOT"] = repo_root + "/.git"
os.environ["GIT_HTTP_EXPORT_ALL"] = ""


def translate_path(self, path):
if self.is_git_request():
Expand Down Expand Up @@ -107,7 +84,7 @@ class WebUiRequestHandler(CGIHTTPRequestHandler):
def do_GET(self):
if self.path.startswith("/git/cat-file/"):
obj = self.path[14:]
self.process(["git", "cat-file", "-p", obj], b"", False)
self.process(["git", "cat-file", "-p", obj], b"", True, False)
elif self.path == "/dirname":
wc = os.path.split(WebUiRequestHandler.REPO_ROOT)[1]
self.send_text(200, codecs.encode(wc, "utf-8"))
Expand All @@ -116,8 +93,10 @@ class WebUiRequestHandler(CGIHTTPRequestHandler):
elif self.path == "/viewonly":
vo = "1" if self.is_view_only() else "0"
self.send_text(200, codecs.encode(vo, "utf-8"))
elif self.is_git_request():
self.process_http_backend()
else:
CGIHTTPRequestHandler.do_GET(self)
SimpleHTTPRequestHandler.do_GET(self)


def do_POST(self):
Expand All @@ -135,42 +114,58 @@ class WebUiRequestHandler(CGIHTTPRequestHandler):
cmd = shlex.split("git " + codecs.decode(args, "utf-8"))
action = cmd[1]
if not self.is_view_only() or args in ["branch", "branch --remotes", "tag"] or action in ["show", "status", "log", "ls-tree"]:
self.process(cmd, stdin, True)
self.process(cmd, stdin, True, True)
else:
self.send_error(403)
elif self.is_git_request():
self.process_http_backend();
else:
CGIHTTPRequestHandler.do_POST(self)
SimpleHTTPRequestHandler.do_POST(self)


def is_view_only(self):
host = self.headers.get("Host", "").split(":")[0]
return host not in allowed_hosts

def is_cgi(self):
"""
This overrides CGIHTTPRequestHandler.is_cgi to consider any request having 'git/*' as User-Agent as a CGI request
"""
if self.is_git_request():
git_http_backend = "git-http-backend"
if IS_WINDOWS:
git_http_backend += ".exe"
self.cgi_info = WebUiRequestHandler.GIT_HTTP_BACKEND_DIR, git_http_backend + self.path
return True
return False

def process_http_backend(self):
parsed_path = urlparse(self.path)

env = {}
env["GIT_PROJECT_ROOT"] = WebUiRequestHandler.REPO_ROOT + "/.git"
env["GIT_HTTP_EXPORT_ALL"] = ""
env["REQUEST_METHOD"] = self.command
env["REMOTE_ADDR"] = self.client_address[0]
env["PATH_INFO"] = parsed_path.path
env["QUERY_STRING"] = parsed_path.query
if 'Content-Type' in self.headers:
env['CONTENT_TYPE'] = self.headers['Content-Type']
if 'Content-Length' in self.headers:
contentLength = self.headers['Content-Length']
env['CONTENT_LENGTH'] = contentLength
inputData = self.rfile.read(int(contentLength))
else:
env['CONTENT_LENGTH'] = '0'
inputData = b""

self.wfile.write(b"HTTP/1.0 200 OK\r\n")
self.wfile.flush()
self.process(['git', 'http-backend'], inputData, False, False, env)


def is_git_request(self):
return self.headers.get("User-Agent", "").startswith("git/")


def process(self, cmd, stdin, addstatus):
self.send_response(200)
self.end_headers()
def process(self, cmd, stdin, add_headers, add_footers, env = None):
if add_headers:
self.send_response(200)
self.end_headers()
# Convention : send first all git output, then stderr.
# Finially we add footers: a blank line followed by key / value pairs as in HTTP headers
if IS_WINDOWS:
# On windows we cannot pipe the process output directly to the socket.
git = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, cwd = WebUiRequestHandler.REPO_ROOT)
git = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, cwd = WebUiRequestHandler.REPO_ROOT, env = env)
git.stdin.write(stdin)
git.stdin.close()
bufferlen = 64 * 1024
Expand All @@ -182,13 +177,15 @@ class WebUiRequestHandler(CGIHTTPRequestHandler):
stderr = git.stderr.read()
git.wait()
else:
git = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = self.wfile, stderr = subprocess.PIPE, cwd = WebUiRequestHandler.REPO_ROOT)
git = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = self.wfile, stderr = subprocess.PIPE, cwd = WebUiRequestHandler.REPO_ROOT, env = env)
stdout, stderr = git.communicate(stdin)
if addstatus:
if add_footers:
self.wfile.write(stderr)
self.wfile.write(b"\r\n")
self.wfile.write(codecs.encode("\r\nGit-Stderr-Length: " + str(len(stderr)), "utf-8"))
self.wfile.write(codecs.encode("\r\nGit-Return-Code: " + str(git.returncode), "utf-8"))
elif git.returncode != 0:
print(stderr)


def send_text(self, http_status, text):
Expand All @@ -214,7 +211,7 @@ def auto_update():
delta = datetime.datetime.now() - datetime.datetime.fromtimestamp(fetch_head_mtime)
if delta > datetime.timedelta(14):
# Check if update is allowed
allow_autoupdate = _read_config_boolean("autoupdate")
allow_autoupdate = read_config_boolean("autoupdate")
if not allow_autoupdate:
return

Expand All @@ -227,7 +224,7 @@ def auto_update():



def _read_config_string(name, default=None):
def read_config_string(name, default=None):
git = subprocess.Popen(["git", "config", "--get", "webui.{}".format(name)], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
out = codecs.decode(git.communicate()[0], "utf-8")
if git.returncode != 0:
Expand All @@ -238,27 +235,27 @@ def _read_config_string(name, default=None):



def _read_config_boolean(name, default=False):
r = _read_config_string(name)
def read_config_boolean(name, default=False):
r = read_config_string(name)
if r == None:
return bool(default)
return str(r).lower() == "true"




def _get_setting_string(args, name, default=None):
def get_setting_string(args, name, default=None):
if vars(args)[name] is not None:
return vars(args)[name]
return _read_config_string(name, default)
return read_config_string(name, default)




def _get_setting_boolean(args, name, default=False):
def get_setting_boolean(args, name, default=False):
if vars(args)[name] is not None:
return vars(args)[name]
return _read_config_boolean(name, default)
return read_config_boolean(name, default)



Expand All @@ -284,21 +281,20 @@ if __name__ == '__main__':
else:
args.repo_root = new_root

writeaccess = _read_config_string("writeaccess")
writeaccess = read_config_string("writeaccess")
if writeaccess is not None:
allowed_hosts = writeaccess.split(',') if writeaccess else []
if args.allow_hosts is not None:
allowed_hosts += args.allow_hosts.split(',')


if args.repo_root is None or '.git' not in os.listdir(args.repo_root):
sys.stderr.write("No git repository found\n")
sys.exit(1)
WebUiRequestHandler.initialize(args.repo_root)

args.port = _get_setting_string(args, 'port', None)
args.port = get_setting_string(args, 'port', None)
port = int(args.port) if args.port is not None else 8000
host = _get_setting_string(args, 'host', "")
host = get_setting_string(args, 'host', "")
httpd = None
while httpd is None:
try:
Expand All @@ -311,10 +307,9 @@ if __name__ == '__main__':
sys.stderr.write("Port {} is already in use, trying another one\n".format(port))
port += 1


url = "http://{}:{}".format(host if host else "localhost", port)
print("Serving at {}".format(url))
nobrowser = _get_setting_boolean(args, "nobrowser", True);
nobrowser = get_setting_boolean(args, "nobrowser", True);
if not nobrowser:
webbrowser.open(url)

Expand Down
Loading

0 comments on commit 908132b

Please sign in to comment.