예제 #1
0
		def git_commit(args):
			if len(args) == 3:
				try:
					repo = Gittle('.')
					print repo.commit(name=args[1],email=args[2],message=args[0])
				except:
					print 'Error: {0}'.format(sys.exc_value)
			else:
				print command_help['commit']
		def git_commit(args):
			if len(args) == 3:
				try:
					repo = Gittle('.')
					print repo.commit(name=args[1],email=args[2],message=args[0])
				except:
					print 'Error: {0}'.format(sys.exc_value)
			else:
				print command_help['commit']
def gitPush():
    logging.info('*** Versioning files and pushing to remote repository ***')
    destinations = [dataDestination, PDFdestination]
    remotes = ['dataRemote', 'PDFRemote']
    for d, r in zip(destinations, remotes):
        repo = Gittle(d, origin_uri=config.get('Git', r))
        repo.stage(repo.pending_files)
        repo.commit(message=commitMessage)
        repo.push()
def gitPush():
    logging.info('*** Versioning files and pushing to remote repository ***')
    destinations = [dataDestination, PDFdestination]
    remotes = ['dataRemote', 'PDFRemote']
    for d, r in zip(destinations, remotes):
        repo = Gittle(d, origin_uri=config.get('Git', r))
        repo.stage(repo.pending_files)
        repo.commit(message=commitMessage)
        repo.push()
예제 #5
0
class MyGit:
    def __init__(self, gitdir):
        self.git = Gittle(gitdir)

    def add(self, files, message):
        self.git.commit(message=message, files=files)

    def rm(self, files, message):
        self.git.rm(files)
        self.git.commit(message=message)
예제 #6
0
class Git(object):
    @classmethod
    def is_dir_git_repo(cls, directory):
        return os.system("git rev-parse --is-inside-work-tree") == 0

    def __init__(self, gitpath):
        self._gitpath = gitpath
        try:
            self._gittle = Gittle(gitpath)
        except dulwich.errors.NotGitRepository:
            raise NoTesseraRepoError()

    @property
    def git_dir(self):
        """
            Returns the git dir.
        """
        return self._gittle.git_dir

    def is_working(self):
        """
            Checks if git is working
        """
        return self._gittle.is_working


    def commit_repo(self, tesserae, message):
        """
            Commits the git tessera files.
        """
        return self._gittle.commit(message=message, files=[os.path.relpath(tesserae.configpath, self._gitpath)])

    def add_tessera(self, tessera):
        """
            Commits a Tessera created by the create() method to the repository.
        """
        return self._gittle.commit(message="tessera created: %s" % tessera.title, files=[os.path.relpath(tessera.tessera_file, self._gitpath), os.path.relpath(tessera.info_file, self._gitpath)])

    def update_tessera(self, tessera):
        """
            Commits an updated Tessera to the repository.
        """
        return self._gittle.commit(message="tessera updated: %s" % tessera.title, files=[os.path.relpath(tessera.tessera_file, self._gitpath), os.path.relpath(tessera.info_file, self._gitpath)])

    def rm_tessera(self, tessera):
        """
            Removes a tessera and commits to git repository.
        """
        files = [str(os.path.relpath(tessera.tessera_file, self._gitpath)), str(os.path.relpath(tessera.info_file, self._gitpath))]
        self._gittle.rm(files)
        return self._gittle.commit(message="tessera removed: %s" % tessera.title, files=files)
예제 #7
0
class GPassGit:

    #Creates a Git object
    def __init__(self, repoPath):
        self.repoPath = repoPath
        self.repo = None
        if self.isRepoSet():
            self.repo = Gittle(self.repoPath)

    #Check For Git Repo
    def isRepoSet(self):
        if os.path.isfile(self.repoPath + '/.git/config'):
            return True
        return False

    def init(self, repoPath):
    	self.repo = Gittle.init(repoPath)
    	print("Created Repo")

    def add(self, filePath):
    	self.repo.stage([filePath])

    def commit(self, user, em, msg):
    	self.repo.commit(
            name=user,
            email=em,
            message=msg
        )

    # Authentication with RSA private key
    def auth(self, key):
        key_file = open(key)
        repo.auth(pkey=key_file)

    def push(self, key):
        self.auth(key)
        self.repo.push()

    def pull(self, key):
        self.auth(key)
        self.repo.pull()

    def acp(self, filepath, user, em, msg):
    	self.add(filepath)
    	self.commit(user, em, msg)
    	self.push(key)
        
예제 #8
0
def GitUpload(file, Name, Email, Password, Repository, Message="Some uploads"):

    origin_uris = Repository
    if not origin_uris.startswith(Name):
        origin_uris = Name + "/" + origin_uris
    if not origin_uris.startswith("https://github.com/"):
        origin_uris = "https://github.com/" + origin_uris
    if not origin_uris.endswith(".git"):
        origin_uris = origin_uris + ".git"

    path = os.getcwd()

    # Gittle.clone() 会将当前目录下的文件下载到本地,并初始化git工作路径,上传文件正常
    # repo = Gittle.clone("https://github.com/fengfeng0918/gittle.git", path)
    # Gittle.init() 初始化git工作路径,并没有将远程仓库信息拉到本地,上传(push)文件时会将远程库清空
    # repo = Gittle.init(path,origin_uri="https://github.com/fengfeng0918/gittle.git")

    # git init  以下流程正常!!!
    if not os.path.exists(".git"):
        local_repo = Gittle.init(path)
        # local_repo = Gittle.clone(origin_uris,path)
        bares = False  #不会删除远端,重写本地
    else:
        local_repo = Repo(path)
        bares = True  # 不会删除远端,不重写本地

    repo = Gittle(local_repo, origin_uris)
    repo.fetch(bare=bares)

    # Stage file
    if not isinstance(file, list):
        file = [file]
    repo.stage(file)

    # Commiting
    repo.commit(name=Name, email=Email, message=Message, files=file)

    # add remote
    repo.add_remote('origin', origin_uris)

    # Push
    repo.auth(username=Name, password=Password)  # Auth for pushing
    repo.push()
예제 #9
0
class GitGittle(BaseGit):
    def __init__(self):
        self.repo = None

    def git_init(self):
        try:
            # Init repository
            logger.debug("Local repository path:{}, Git server url: {}".format(
                conf.git.local_repository_path, conf.git.git_server_url))
            self.repo = Gittle(conf.git.local_repository_path,
                               origin_uri=conf.git.git_server_url)

            logger.info("Pulling from git..")
            # Update local working copy
            self.repo.pull()

            logger.info("GitGittle - Git is up to date !")

        except Exception as exc:
            logger.error(
                "GitGittle - Failed to initialize Git. Reason: {}".format(
                    exc.message))
            raise GitInitError(exc.message)

    def git_upload_changes(self):
        commit_id = ""
        try:

            logger.info("Commit changes in progress ..")
            # Stage modified files
            self.repo.stage(self.repo.pending_files)

            commit_message = conf.git.commit_message_format.format(
                self.repo.added_files)
            # Commit the change
            commit_id = self.repo.commit(conf.git.commit_user,
                                         conf.git.commit_email, commit_message)

            logger.info("Commit details: commit_user:{}, commit_email:{}, "
                        "commit_message:{}, commit_id:{}".format(
                            conf.git.commit_user, conf.git.commit_email,
                            commit_message, commit_id))

            # Push to repository
            self.repo.push()

        except Exception as exc:
            logger.error("GitGittle - Filed to upload file to git.")
            raise GitUploadError("Failed to upload file to Git")

        return commit_id

    def validate_git(self):
        pass
예제 #10
0
class MyGit:
    def __init__(self, gitdir):
        self.git = Gittle(gitdir)

    def add(self, files, message):
        self.git.commit(message=message, files=files)

    def rm(self, files, message):
        self.git.rm(files)
        self.git.commit(message=message)

    def read_author(self, tessera_path):
        author = "unknown"
        author_time = 0;
        walker = self.git.repo.get_walker(paths=[tessera_path])
        try:
            c = iter(walker).next().commit
        except StopIteration:
            print "git: author not found in %s" % tessera_path
        else:
            author = c.author
            author_time = c.author_time
        return (author, author_time)
예제 #11
0
 def git_pull(self, TMP_DIR, CODE_DIR):
     ''' git pull code
         use commit id tag you code
     lastest = [info['sha'] for info in repo.commit_info()[1:3]]
     print((repo.diff(*lastest, diff_type='classic')))
     '''
     print("========%s: git pull for env:test=========" % self.PRO_NAME)
     repo = Gittle(self.CODE_DIR, self.REPO_URL)
     command = 'cd %s && git pull' % self.CODE_DIR
     os.system('command')
     COMMIT_ID = repo.commit()[0:-30]
     CVER = "%s_%s_%s" % (self.PRO_NAME, self.CTIME, COMMIT_ID)
     CODE_TMP = '%s/%s' % (TMP_DIR, CVER)
     shutil.copytree(CODE_DIR, CODE_TMP)
     echo_info("git pull success")
     return CVER
예제 #12
0
class Wiki(HookMixin):
    path = None
    base_path = '/'
    default_ref = 'master'
    default_committer_name = 'Anon'
    default_committer_email = '*****@*****.**'
    index_page = 'home'
    gittle = None
    repo = None

    def __init__(self, path):
        try:
            self.gittle = Gittle(path)
        except NotGitRepository:
            self.gittle = Gittle.init(path)

        # Dulwich repo
        self.repo = self.gittle.repo

        self.path = path

    def __repr__(self):
        return "Wiki: %s" % self.path

    def _get_user(self, username, email):
        if not username:
            username = self.default_committer_name

        if not email:
            email = self.default_committer_email

        return username, email

    def _cache_key(self, name, sha='HEAD'):
        return 'page/%s[%s]' % (name, sha)

    def revert_page(self, name, commit_sha, message, username, email):
        """Revert page to passed commit sha1

        :param name:  Name of page to revert.
        :param commit_sha: Commit Sha1 to revert to.
        :param message: Commit message.
        :param username: Committer name.
        :param email: Committer email.
        :return: Git commit sha1

        """
        page = self.get_page(name, commit_sha)
        if not page:
            raise PageNotFound('Commit not found')

        if not message:
            commit_info = gittle.utils.git.commit_info(
                self.gittle[commit_sha.encode('latin-1')])
            message = commit_info['message']

        return self.write_page(name,
                               page['data'],
                               message=message,
                               username=username,
                               email=email)

    def write_page(self,
                   name,
                   content,
                   message=None,
                   create=False,
                   username=None,
                   email=None):
        """Write page to git repo

        :param name: Name of page.
        :param content: Content of page.
        :param message: Commit message.
        :param create: Perform git add operation?
        :param username: Commit Name.
        :param email: Commit Email.
        :return: Git commit sha1.
        """

        cname = to_canonical(name)
        filename = cname_to_filename(cname)
        dirname = posixpath.join(self.path, posixpath.dirname(filename))

        if not os.path.exists(dirname):
            os.makedirs(dirname)

        with open(self.path + "/" + filename, 'w') as f:
            f.write(content)

        if create:
            self.gittle.add(filename)

        if not message:
            message = "Updated %s" % name

        username, email = self._get_user(username, email)

        ret = self.gittle.commit(name=username,
                                 email=email,
                                 message=message,
                                 files=[filename])

        cache.delete(self._cache_key(cname))

        return ret

    def rename_page(self,
                    old_name,
                    new_name,
                    username=None,
                    email=None,
                    message=None):
        """Rename page.

        :param old_name: Page that will be renamed.
        :param new_name: New name of page.
        :param username: Committer name
        :param email: Committer email
        :return: str -- Commit sha1

        """
        old_filename, new_filename = map(cname_to_filename,
                                         [old_name, new_name])
        if old_filename not in self.gittle.index:
            # old doesn't exist
            return None

        if old_filename == new_filename:
            return

        if new_filename in self.gittle.index:
            # file is being overwritten, but that is ok, it's git!
            pass

        username, email = self._get_user(username, email)

        if not message:
            message = "Moved %s to %s" % (old_name, new_name)

        os.rename(os.path.join(self.path, old_filename),
                  os.path.join(self.path, new_filename))

        self.gittle.add(new_filename)
        self.gittle.rm(old_filename)

        commit = self.gittle.commit(name=username,
                                    email=email,
                                    message=message,
                                    files=[old_filename, new_filename])

        cache.delete_many(self._cache_key(old_name), self._cache_key(new_name))

        return commit

    def delete_page(self, name, username=None, email=None, message=None):
        """Delete page.
        :param name: Page that will be deleted
        :param username: Committer name
        :param email: Committer email
        :return: str -- Commit sha1

        """

        username, email = self._get_user(username, email)

        if not message:
            message = "Deleted %s" % name

        filename = cname_to_filename(name)

        # gittle.rm won't actually remove the file, have to do it ourselves
        os.remove(os.path.join(self.path, filename))
        self.gittle.rm(filename)
        commit = self.gittle.commit(name=username,
                                    email=email,
                                    message=message,
                                    files=[filename])
        cache.delete_many(self._cache_key(name))
        return commit

    def get_page(self, name, sha='HEAD'):
        """Get page data, partials, commit info.

        :param name: Name of page.
        :param sha: Commit sha.
        :return: dict

        """
        cached = cache.get(self._cache_key(name, sha))
        if cached:
            return cached

        # commit = gittle.utils.git.commit_info(self.repo[sha])
        filename = cname_to_filename(name).encode('utf8')
        sha = sha.encode('latin-1')

        try:
            data = self.gittle.get_commit_files(sha,
                                                paths=[filename]).get(filename)
            if not data:
                return None
            partials = {}
            if data.get('data'):
                meta = self.get_meta(data['data'])
                if meta and 'import' in meta:
                    for partial_name in meta['import']:
                        partials[partial_name] = self.get_page(partial_name)
            data['partials'] = partials
            data['info'] = self.get_history(name, limit=1)[0]
            cache.set(self._cache_key(name, sha), data)
            return data

        except KeyError:
            # HEAD doesn't exist yet
            return None

    def get_meta(self, content):
        """Get metadata from page if any.

        :param content: Page content
        :return: dict

        """
        if not content.startswith("---"):
            return None

        meta_end = re.search("\n(\.{3}|\-{3})", content)

        if not meta_end:
            return None

        try:
            return yaml.safe_load(content[0:meta_end.start()])
        except Exception as e:
            return {'error': e.message}

    def compare(self, name, old_sha, new_sha):
        """Compare two revisions of the same page.

        :param name: Name of page.
        :param old_sha: Older sha.
        :param new_sha: Newer sha.
        :return: str - Raw markup with styles

        """

        # TODO: This could be effectively done in the browser
        old = self.get_page(name, sha=old_sha)
        new = self.get_page(name, sha=new_sha)
        return ghdiff.diff(old['data'], new['data'])

    def get_index(self):
        """Get repo index of head.

        :return: list -- List of dicts

        """
        rv = []
        index = self.repo.open_index()
        for name in index:
            rv.append(
                dict(name=filename_to_cname(name),
                     filename=name,
                     ctime=index[name].ctime[0],
                     mtime=index[name].mtime[0],
                     sha=index[name].sha,
                     size=index[name].size))

        return rv

    def get_history(self, name, limit=100):
        """Get page history.

        :param name: Name of page.
        :param limit: Limit history size.
        :return: list -- List of dicts

        """
        if not len(self.repo.open_index()):
            # Index is empty, no commits
            return []

        file_path = cname_to_filename(name)
        versions = []

        walker = self.repo.get_walker(paths=[file_path], max_entries=limit)
        for entry in walker:
            change_type = None
            for change in entry.changes():
                if change.old.path == file_path:
                    change_type = change.type
                elif change.new.path == file_path:
                    change_type = change.type
            author_name, author_email = entry.commit.author.rstrip('>').split(
                '<')
            versions.append(
                dict(author=author_name.strip(),
                     author_email=author_email,
                     time=entry.commit.author_time,
                     message=entry.commit.message,
                     sha=entry.commit.id,
                     type=change_type))

        return versions
예제 #13
0
class Wiki(HookMixin):
    path = None
    base_path = '/'
    default_ref = 'master'
    default_committer_name = 'Anon'
    default_committer_email = '*****@*****.**'
    index_page = 'home'
    gittle = None
    repo = None

    def __init__(self, path):
        try:
            self.gittle = Gittle(path)
        except NotGitRepository:
            self.gittle = Gittle.init(path)

        # Dulwich repo
        self.repo = self.gittle.repo

        self.path = path

    def __repr__(self):
        return "Wiki: %s" % self.path

    def revert_page(self, name, commit_sha, message, username):
        page = self.get_page(name, commit_sha)
        if not page:
            # Page not found
            return None
        commit_info = gittle.utils.git.commit_info(self.gittle[commit_sha.encode('latin-1')])
        message = commit_info['message']
        return self.write_page(name, page['data'], message=message, username=username)

    def write_page(self, name, content, message=None, create=False, username=None, email=None):

        def escape_repl(m):
            if m.group(1):
                return "```" + escape(m.group(1)) + "```"

        def unescape_repl(m):
            if m.group(1):
                return "```" + unescape(m.group(1)) + "```"

        cname = to_canonical(name)

        # prevents p tag from being added, we remove this later
        content = '<div>' + content + '</div>'
        content = re.sub(r"```(.*?)```", escape_repl, content, flags=re.DOTALL)

        tree = lxml.html.fromstring(content)

        cleaner = Cleaner(remove_unknown_tags=False,
                          kill_tags=set(['style']),
                          safe_attrs_only=False)
        tree = cleaner.clean_html(tree)

        content = lxml.html.tostring(tree, encoding='utf-8', method='html')

        # remove added div tags
        content = content[5:-6]

        # FIXME this is for block quotes, doesn't work for double ">"
        content = re.sub(r"(\n&gt;)", "\n>", content)
        content = re.sub(r"(^&gt;)", ">", content)

        # Handlebars partial ">"
        content = re.sub(r"\{\{&gt;(.*?)\}\}", r'{{>\1}}', content)

        # Handlebars, allow {{}} inside HTML links
        content = content.replace("%7B", "{")
        content = content.replace("%7D", "}")

        content = re.sub(r"```(.*?)```", unescape_repl, content, flags=re.DOTALL)

        filename = cname_to_filename(cname)
        with open(self.path + "/" + filename, 'w') as f:
            f.write(content)

        if create:
            self.gittle.add(filename)

        if not message:
            message = "Updated %s" % name

        if not username:
            username = self.default_committer_name

        if not email:
            email = self.default_committer_email

        ret = self.gittle.commit(name=username,
                                 email=email,
                                 message=message,
                                 files=[filename])

        cache.delete(cname)

        return ret

    def rename_page(self, old_name, new_name, user=None):
        old_filename, new_filename = map(cname_to_filename, [old_name, new_name])
        if old_filename not in self.gittle.index:
            # old doesn't exist
            return None

        if new_filename in self.gittle.index:
            # file is being overwritten, but that is ok, it's git!
            pass

        os.rename(os.path.join(self.path, old_filename), os.path.join(self.path, new_filename))

        self.gittle.add(new_filename)
        self.gittle.rm(old_filename)

        self.gittle.commit(name=getattr(user, 'username', self.default_committer_name),
                           email=getattr(user, 'email', self.default_committer_email),
                           message="Moved %s to %s" % (old_name, new_name),
                           files=[old_filename, new_filename])

        cache.delete_many(old_filename, new_filename)

    def get_page(self, name, sha='HEAD'):
        cached = cache.get(name)
        if cached:
            return cached

        # commit = gittle.utils.git.commit_info(self.repo[sha])
        filename = cname_to_filename(name).encode('latin-1')
        sha = sha.encode('latin-1')

        try:
            data = self.gittle.get_commit_files(sha, paths=[filename]).get(filename)
            if not data:
                return None
            partials = {}
            if data.get('data'):
                meta = self.get_meta(data['data'])
                if meta and 'import' in meta:
                    for partial_name in meta['import']:
                        partials[partial_name] = self.get_page(partial_name)
            data['partials'] = partials
            data['info'] = self.get_history(name, limit=1)[0]
            return data

        except KeyError:
            # HEAD doesn't exist yet
            return None

    def get_meta(self, content):
        if not content.startswith("---"):
            return None
        meta_end = re.search("\n(\.{3}|\-{3})", content)
        if not meta_end:
            return None
        try:
            return yaml.safe_load(content[0:meta_end.start()])
        except Exception as e:
            return {'error': e.message}

    def compare(self, name, old_sha, new_sha):
        old = self.get_page(name, sha=old_sha)
        new = self.get_page(name, sha=new_sha)
        return ghdiff.diff(old['data'], new['data'])

    def get_index(self):
        rv = []
        index = self.repo.open_index()
        for name in index:
            rv.append(dict(name=filename_to_cname(name),
                           filename=name,
                           ctime=index[name].ctime[0],
                           mtime=index[name].mtime[0],
                           sha=index[name].sha,
                           size=index[name].size))

        return rv

    def get_history(self, name, limit=100):
        file_path = cname_to_filename(name)
        versions = []
        walker = self.repo.get_walker(paths=[file_path], max_entries=limit)
        for entry in walker:
            change_type = None
            for change in entry.changes():
                if change.old.path == file_path:
                    change_type = change.type
                elif change.new.path == file_path:
                    change_type = change.type
            author_name, author_email = entry.commit.author.split('<')
            versions.append(dict(
                author=author_name.strip(),
                time=entry.commit.author_time,
                message=entry.commit.message,
                sha=entry.commit.id,
                type=change_type))

        return versions
예제 #14
0
class Wiki(HookMixin):
    path = None
    base_path = '/'
    default_ref = 'master'
    default_committer_name = 'Anon'
    default_committer_email = '*****@*****.**'
    index_page = 'home'
    gittle = None
    repo = None

    def __init__(self, path):
        try:
            self.gittle = Gittle(path)
        except NotGitRepository:
            self.gittle = Gittle.init(path)

        # Dulwich repo
        self.repo = self.gittle.repo

        self.path = path

    def __repr__(self):
        return "Wiki: %s" % self.path

    def _get_user(self, username, email):
        if not username:
            username = self.default_committer_name

        if not email:
            email = self.default_committer_email

        return username, email

    def revert_page(self, name, commit_sha, message, username, email):
        """Revert page to passed commit sha1

        :param name:  Name of page to revert.
        :param commit_sha: Commit Sha1 to revert to.
        :param message: Commit message.
        :param username: Committer name.
        :param email: Committer email.
        :return: Git commit sha1

        """
        page = self.get_page(name, commit_sha)
        if not page:
            raise PageNotFound('Commit not found')

        if not message:
            commit_info = gittle.utils.git.commit_info(self.gittle[commit_sha.encode('latin-1')])
            message = commit_info['message']

        return self.write_page(name, page['data'], message=message, username=username, email=email)

    def write_page(self, name, content, message=None, create=False, username=None, email=None):
        """Write page to git repo

        :param name: Name of page.
        :param content: Content of page.
        :param message: Commit message.
        :param create: Perform git add operation?
        :param username: Commit Name.
        :param email: Commit Email.
        :return: Git commit sha1.
        """

        cname = to_canonical(name)
        filename = cname_to_filename(cname)
        namespace_path = os.path.join(self.path, os.path.split(filename)[0])

        if not os.path.exists(namespace_path):
            os.makedirs(namespace_path)

        with open(self.path + "/" + filename, 'w') as f:
            f.write(content)

        if create:
            self.gittle.add(filename)

        if not message:
            message = "Updated %s" % name

        username, email = self._get_user(username, email)

        ret = self.gittle.commit(name=username,
                                 email=email,
                                 message=message,
                                 files=[filename])

        cache.delete(cname)

        return ret

    def rename_page(self, old_name, new_name, username=None, email=None, message=None):
        """Rename page.

        :param old_name: Page that will be renamed.
        :param new_name: New name of page.
        :param username: Committer name
        :param email: Committer email
        :return: str -- Commit sha1

        """
        old_filename, new_filename = map(cname_to_filename, [old_name, new_name])
        if old_filename not in self.gittle.index:
            # old doesn't exist
            return None

        if new_filename in self.gittle.index:
            # file is being overwritten, but that is ok, it's git!
            pass

        username, email = self._get_user(username, email)

        if not message:
            message = "Moved %s to %s" % (old_name, new_name)

        os.rename(os.path.join(self.path, old_filename), os.path.join(self.path, new_filename))

        self.gittle.add(new_filename)
        self.gittle.rm(old_filename)

        commit = self.gittle.commit(name=username,
                                    email=email,
                                    message=message,
                                    files=[old_filename, new_filename])

        cache.delete_many(old_name, new_name)

        return commit

    def delete_page(self, name, username=None, email=None, message=None):
        """Delete page.
        :param name: Page that will be deleted
        :param username: Committer name
        :param email: Committer email
        :return: str -- Commit sha1

        """

        username, email = self._get_user(username, email)

        if not message:
            message = "Deleted %s" % name

        filename = cname_to_filename(name)
        self.gittle.rm(filename)
        commit = self.gittle.commit(name=username,
                                    email=email,
                                    message=message,
                                    files=[str(filename)])
        cache.delete_many(name)
        return commit

    def get_page(self, name, sha='HEAD'):
        """Get page data, partials, commit info.

        :param name: Name of page.
        :param sha: Commit sha.
        :return: dict

        """
        cached = cache.get(name)
        if cached:
            return cached

        # commit = gittle.utils.git.commit_info(self.repo[sha])
        filename = cname_to_filename(name).encode('latin-1')
        sha = sha.encode('latin-1')

        namespace_path = os.path.join(self.path, os.path.splitext(filename)[0])
        namespace_cname = to_canonical(os.path.splitext(filename)[0])
        if not os.path.exists(os.path.join(self.path, filename)) and os.path.isdir(namespace_path):
            files = ["[%s](%s_%s)" % (x, namespace_cname, filename_to_cname(x)) for x in os.listdir(namespace_path)]
            print(files)
            return {'data': "# Namespace %s \n\n This is an automatically generated list of pages in this namespace.\n\n %s" % (os.path.splitext(filename)[0], '\n'.join(files))}

        try:
            data = self.gittle.get_commit_files(sha, paths=[filename]).get(filename)
            if not data:
                return None
            partials = {}
            if data.get('data'):
                meta = self.get_meta(data['data'])
                if meta and 'import' in meta:
                    for partial_name in meta['import']:
                        partials[partial_name] = self.get_page(partial_name)
            data['partials'] = partials
            data['info'] = self.get_history(name, limit=1)[0]

            return data

        except KeyError:
            # HEAD doesn't exist yet
            return None

    def get_meta(self, content):
        """Get metadata from page if any.

        :param content: Page content
        :return: dict

        """
        if not content.startswith("---"):
            return None

        meta_end = re.search("\n(\.{3}|\-{3})", content)

        if not meta_end:
            return None

        try:
            return yaml.safe_load(content[0:meta_end.start()])
        except Exception as e:
            return {'error': e.message}

    def compare(self, name, old_sha, new_sha):
        """Compare two revisions of the same page.

        :param name: Name of page.
        :param old_sha: Older sha.
        :param new_sha: Newer sha.
        :return: str - Raw markup with styles

        """

        # TODO: This could be effectively done in the browser
        old = self.get_page(name, sha=old_sha)
        new = self.get_page(name, sha=new_sha)
        return ghdiff.diff(old['data'], new['data'])

    def get_index(self):
        """Get repo index of head.

        :return: list -- List of dicts

        """
        rv = []
        index = self.repo.open_index()
        for name in index:
            rv.append(dict(name=filename_to_cname(name),
                           filename=name,
                           ctime=index[name].ctime[0],
                           mtime=index[name].mtime[0],
                           sha=index[name].sha,
                           size=index[name].size))

        return rv

    def get_history(self, name, limit=100):
        """Get page history.

        :param name: Name of page.
        :param limit: Limit history size.
        :return: list -- List of dicts

        """
        if not len(self.repo.open_index()):
            # Index is empty, no commits
            return []

        file_path = cname_to_filename(name)
        versions = []

        walker = self.repo.get_walker(paths=[file_path], max_entries=limit)
        for entry in walker:
            change_type = None
            for change in entry.changes():
                if change.old.path == file_path:
                    change_type = change.type
                elif change.new.path == file_path:
                    change_type = change.type
            author_name, author_email = entry.commit.author.split('<')
            versions.append(dict(
                author=author_name.strip(),
                time=entry.commit.author_time,
                message=entry.commit.message,
                sha=entry.commit.id,
                type=change_type))

        return versions
예제 #15
0
class Wiki(HookMixin):
    path = None
    base_path = '/'
    default_ref = 'master'
    default_committer_name = 'Anon'
    default_committer_email = '*****@*****.**'
    index_page = 'home'
    gittle = None
    repo = None

    def __init__(self, path):
        try:
            self.gittle = Gittle(path)
        except NotGitRepository:
            self.gittle = Gittle.init(path)

        # Dulwich repo
        self.repo = self.gittle.repo

        self.path = path

    def __repr__(self):
        return "Wiki: %s" % self.path

    def commit(self, name, email, message, files):
        """Commit to the underlying git repo.

        :param name: Committer name
        :param email: Committer email
        :param message: Commit message
        :param files: list of file names that should be committed
        :return:
        """
        # Dulwich and gittle seem to want us to encode ourselves at the moment. see #152
        if isinstance(name, unicode):
            name = name.encode('utf-8')
        if isinstance(email, unicode):
            email = email.encode('utf-8')
        if isinstance(message, unicode):
            message = message.encode('utf-8')
        return self.gittle.commit(name=name,
                                  email=email,
                                  message=message,
                                  files=files)

    def get_page(self, name, sha='HEAD'):
        """Get page data, partials, commit info.

        :param name: Name of page.
        :param sha: Commit sha.
        :return: dict

        """
        return WikiPage(name, self, sha=sha)

    def get_index(self):
        """Get repo index of head.

        :return: list -- List of dicts

        """
        rv = []
        index = self.repo.open_index()
        for name in index:
            rv.append(dict(name=filename_to_cname(name),
                           filename=name,
                           ctime=index[name].ctime[0],
                           mtime=index[name].mtime[0],
                           sha=index[name].sha,
                           size=index[name].size))

        return rv
예제 #16
0
class GitCommands(object):

    def __init__(self):
        self.gitdir = "."
        self.git = Gittle(self.gitdir)
        Tessera._tesserae = os.path.relpath("%s/.tesserae" % self.gitdir)

    def cmd_init(self, args):
        if len(args) != 0:
            stderr.write("git tessera init takes no arguments\n")
            return False

        #if self.git.is_dirty():
            #stderr.write("repo is dirty\n")
            #return False

        if os.path.exists(Tessera._tesserae):
            stderr.write("git tesserae directory already exists: %s\n" % Tessera._tesserae)
            return False
        os.mkdir(Tessera._tesserae)

        files = []
        t = "%s/template" % Tessera._tesserae
        shutil.copyfile("%s/config/template" % os.path.dirname(os.path.realpath(__file__)), t)
        files.append(t)

        t = "%s/status" % Tessera._tesserae
        shutil.copyfile("%s/config/status" % os.path.dirname(os.path.realpath(__file__)), t)
        files.append(t)

        t = "%s/types" % Tessera._tesserae
        shutil.copyfile("%s/config/types" % os.path.dirname(os.path.realpath(__file__)), t)
        files.append(t)

        self.git_add(files, "tessera: initialized")
        return True

    def cmd_ls(self, args):
        gt = GitTessera()
        tesserae = gt.ls(args)
        for t in tesserae:
            print t.summary()
        return True

    def cmd_show(self, args):
        if len(args) != 1:
            stderr.write("git tessera show takes identifier as argument\n")
            return False

        gt = GitTessera()
        t = gt.get(args[0])
        if not t:
            return False

        short = t.summary()
        length = len(short)
        print "=" * length
        print short
        print "=" * length
        print t.content
        return True

    def cmd_edit(self, args):
        if len(args) < 1:
            stderr.write("git tessera edit takes one or more identifier as argument\n")
            return False

        tessera_paths = []
        for key in args:
            tessera_path = None
            found = False
            for i in os.listdir(Tessera._tesserae):
                tessera_path = "%s/%s" % (Tessera._tesserae, i)
                if not stat.S_ISDIR(os.lstat(tessera_path).st_mode):
                    continue
                if i.split('-')[0] == key or i == key:
                    found = True
                    break
            if not found:
                stderr.write("git tessera %s not found\n" % key)
                return False

            tessera_paths.append(tessera_path)

        tessera_files = ["%s/tessera" % x for x in tessera_paths]
        p = Popen(["sensible-editor"] + tessera_files)
        p.communicate()
        p.wait()

        #if self.git.is_dirty():
        for tessera_path in tessera_paths:
            t = Tessera(tessera_path)
            self.git_add("%s/tessera" % tessera_path, "tessera updated: %s" % t.title)
        return True

    def cmd_create(self, args):
        if len(args) < 1:
            stderr.write("git tessera create needs arguments\n")
            return False

        #if self.git.is_dirty():
        #    stderr.write("repo is dirty\n")
        #    return False

        if args:
            title = " ".join(args)
        else:
            title = "tessera title goes here"
        uuid = uuid1()
        tessera_path = "%s/%s" % (Tessera._tesserae, uuid)
        tessera_file = "%s/tessera" % tessera_path
        os.mkdir(tessera_path)
        fin = open("%s/template" % Tessera._tesserae, "r")
        fout = open(tessera_file, "w")
        for line in fin.readlines():
            if line == "@title@\n":
                line = "# %s\n" % title
            fout.write(line)
        fin.close()
        fout.close()

        p = Popen(["sensible-editor", tessera_file])
        p.communicate()
        p.wait()

        t = Tessera(tessera_path)
        self.git_add(tessera_file, "tessera created: %s" % t.get_attribute("title"))
        return True

    def cmd_remove(self, args):
        if len(args) != 1:
            stderr.write("git tessera remove takes identifier as argument\n")
            return False

        #if self.git.is_dirty():
            #stderr.write("repo is dirty\n")
            #return False

        key = args[0]
        tessera_file = None
        tessera_path = None
        for i in os.listdir(Tessera._tesserae):
            tessera_path = "%s/%s" % (Tessera._tesserae, i)
            if not stat.S_ISDIR(os.lstat(tessera_path).st_mode):
                continue
            if i.split('-')[0] == key or i == key:
                tessera_file = "%s/tessera" % tessera_path
                break
        if not tessera_file:
            stderr.write("git tessera %s not found\n" % key)
            return False

        t = Tessera(tessera_path)
        stdout.write("remove tessera %s: %s ? [Y/n] " % (key, t.get_attribute("title")))
        try:
            answer = stdin.readline().strip()
        except KeyboardInterrupt:
            return False
        if not answer or answer.lower() == "y":
            files = ["%s/%s" % (tessera_path, x) for x in os.listdir(tessera_path)]
            self.git_rm(files, "tessera removed: %s" % t.get_attribute("title"))

            from shutil import rmtree
            rmtree(tessera_path)

    def cmd_serve(self, args):
        from tesseraweb import TesseraWeb
        web = TesseraWeb()
        web.serve()

    def cmd_tag(self, args):
        if len(args) != 2:
            stderr.write("git tessera show takes identifier as argument and new tag\n")
            return False

        key = args[0]
        for i in os.listdir(Tessera._tesserae):
            tessera_path = "%s/%s" % (Tessera._tesserae, i)
            if not stat.S_ISDIR(os.lstat(tessera_path).st_mode):
                continue
            if i.split('-')[0] == key or i == key:
                break
        if not tessera_path:
            stderr.write("git tessera %s not found\n" % key)
            return False

        t = Tessera(tessera_path)
        t.add_tag(args[1])
        self.git_add(t.filename, "tessera updated: add tag %s to %s" % (args[1], t.get_attribute("title")))
        return True

    def git_add(self, files, message):
        stderr.write("staging %s" % files)
        self.git.commit(message=message, files=files)

    def git_rm(self, files, message):
        self.git.rm(files)
        self.git.commit(message=message)