Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add git fs storage #823

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/projects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ Git versioning can be enabled by creating a `local_settings.py` file in the `sly
.. code-block:: python

import os

SPEC_FACTORY = {
'PROJECT_SPEC': 'slyd.gitstorage.projectspec.ProjectSpec',
'PROJECT_MANAGER': 'slyd.gitstorage.projects.ProjectsManager',
'PARAMS': {
'storage_backend': 'dulwich.repo.Repo',
'storage_backend': 'fs_repo.repo.FsRepo',
'location': os.environ.get('PORTIA_DATA_DIR', SPEC_DATA_DIR)
},
'CAPABILITIES': {
Expand Down
Empty file.
73 changes: 73 additions & 0 deletions portia_server/fs_repo/repo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import errno
import os
import six
import sys
from django.conf import settings
from dulwich.object_store import PACKDIR
from dulwich.repo import (
Repo, BASE_DIRECTORIES, CONTROLDIR, DEFAULT_REF, OBJECTDIR
)


def root_path(name):
return os.path.join(settings.MEDIA_ROOT, name)


def maybe_mkdirs(path):
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
six.reraise(*sys.exc_info())


class FsRepo(Repo):
def __init__(self, name):
self._name = name
super(FsRepo, self).__init__(root_path(name or ''))
self.bare = True

def head(self):
"""Return the SHA1 pointed at by HEAD."""
return self.refs['refs/heads/master']

@classmethod
def init_bare(cls, path):
return super(FsRepo, cls).init_bare(
os.path.join(root_path(path), CONTROLDIR))

@classmethod
def _init_maybe_bare(cls, path, bare):
for d in BASE_DIRECTORIES:
maybe_mkdirs(os.path.join(path, *d))
objectdir_path = os.path.join(path, OBJECTDIR)
for d in ('info', PACKDIR):
maybe_mkdirs(os.path.join(objectdir_path, d))
ret = cls(path)
ret.refs.set_symbolic_ref(b'HEAD', DEFAULT_REF)
ret._init_files(bare)
return ret

@classmethod
def open(cls, name):
"""Open an existing repository."""
return cls(name)

@classmethod
def repo_exists(cls, name):
"""Check if a repository exists."""
return (
os.path.isdir(root_path(name)) and
os.path.isdir(os.path.join(root_path(name), CONTROLDIR))
)

@classmethod
def list_repos(cls):
"""List all repository names."""
return [d for d in os.listdir(settings.MEDIA_ROOT)
if cls.repo_exists(d)]

@classmethod
def delete_repo(cls, name):
"""Delete a repository."""
os.remove(root_path(name))
13 changes: 8 additions & 5 deletions portia_server/storage/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
try:
from dulwich.diff_tree import tree_changes
from dulwich.objects import Blob, Tree
from dulwich.errors import ObjectMissing
from dulwich.errors import NotGitRepository, ObjectMissing
except ImportError:
pass # Dulwich not required when using FS backend
from six import iteritems, text_type, string_types
Expand Down Expand Up @@ -69,8 +69,8 @@ def init_project(self):
def get_projects(cls, user):
# return an OrderedDict of id => name pairs
try:
dirs, _ = cls('').listdir('')
return OrderedDict((project, project) for project in dirs)
projects = Repoman.list_repos()
return OrderedDict((project, project) for project in projects)
except OSError as ex:
if ex.errno != errno.ENOENT:
six.reraise(*sys.exc_info())
Expand Down Expand Up @@ -194,7 +194,10 @@ def __init__(self, name, author=None):
return
self._tree, self._working_tree = None, None
self.author = author
repo = Repoman.open_repo(name, author)
try:
repo = Repoman.open_repo(name, author)
except NotGitRepository:
repo = Repoman.create_repo(name, author)
self.repo = repo
self.branch = branch = (author and author.username) or DEFAULT_USER
self.checkout(branch=branch)
Expand Down Expand Up @@ -244,7 +247,7 @@ def checkout(self, commit=None, branch=None, retry=True):
@classmethod
def setup(cls):
Repoman.setup(getattr(settings, 'GITSTORAGE_REPO_BACKEND',
'dulwich.repo.Repo'))
'fs_repo.repo.FsRepo'))

def _open(self, name, mode='rb'):
name = self.path(name)
Expand Down
2 changes: 1 addition & 1 deletion portia_server/storage/repoman.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def setup(cls, storage_backend):
def create_repo(cls, repo_name, author=None):
"""Create a new repository named repo_name."""
if cls.storage.repo_exists(repo_name):
raise NameError()
raise NameError('Project already exists with that name')
repoman = cls(author)
repoman._repo = cls.storage.init_bare(repo_name)
tree = Tree()
Expand Down