218 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
#
 | 
						|
# Copyright 2010-2014 The pygit2 contributors
 | 
						|
#
 | 
						|
# This file is free software; you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License, version 2,
 | 
						|
# as published by the Free Software Foundation.
 | 
						|
#
 | 
						|
# In addition to the permissions in the GNU General Public License,
 | 
						|
# the authors give you unlimited permission to link the compiled
 | 
						|
# version of this file into combinations with other programs,
 | 
						|
# and to distribute those combinations without any restriction
 | 
						|
# coming from the use of this file.  (The General Public License
 | 
						|
# restrictions do apply in other respects; for example, they cover
 | 
						|
# modification of the file, and distribution when not linked into
 | 
						|
# a combined executable.)
 | 
						|
#
 | 
						|
# This file is distributed in the hope that it will be useful, but
 | 
						|
# WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
# General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with this program; see the file COPYING.  If not, write to
 | 
						|
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 | 
						|
# Boston, MA 02110-1301, USA.
 | 
						|
 | 
						|
# Import from the Standard Library
 | 
						|
from string import hexdigits
 | 
						|
 | 
						|
# Import from pygit2
 | 
						|
from _pygit2 import Repository as _Repository
 | 
						|
from _pygit2 import GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE
 | 
						|
from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN
 | 
						|
from _pygit2 import GIT_CHECKOUT_SAFE_CREATE, GIT_DIFF_NORMAL
 | 
						|
from _pygit2 import Reference, Tree, Commit, Blob
 | 
						|
 | 
						|
 | 
						|
class Repository(_Repository):
 | 
						|
 | 
						|
    #
 | 
						|
    # Mapping interface
 | 
						|
    #
 | 
						|
    def get(self, key, default=None):
 | 
						|
        value = self.git_object_lookup_prefix(key)
 | 
						|
        return value if (value is not None) else default
 | 
						|
 | 
						|
 | 
						|
    def __getitem__(self, key):
 | 
						|
        value = self.git_object_lookup_prefix(key)
 | 
						|
        if value is None:
 | 
						|
            raise KeyError(key)
 | 
						|
        return value
 | 
						|
 | 
						|
 | 
						|
    def __contains__(self, key):
 | 
						|
        return self.git_object_lookup_prefix(key) is not None
 | 
						|
 | 
						|
 | 
						|
    #
 | 
						|
    # References
 | 
						|
    #
 | 
						|
    def create_reference(self, name, target, force=False):
 | 
						|
        """
 | 
						|
        Create a new reference "name" which points to an object or to another
 | 
						|
        reference.
 | 
						|
 | 
						|
        Based on the type and value of the target parameter, this method tries
 | 
						|
        to guess whether it is a direct or a symbolic reference.
 | 
						|
 | 
						|
        Keyword arguments:
 | 
						|
 | 
						|
        force
 | 
						|
            If True references will be overridden, otherwise (the default) an
 | 
						|
            exception is raised.
 | 
						|
 | 
						|
        Examples::
 | 
						|
 | 
						|
            repo.create_reference('refs/heads/foo', repo.head.hex)
 | 
						|
            repo.create_reference('refs/tags/foo', 'refs/heads/master')
 | 
						|
            repo.create_reference('refs/tags/foo', 'bbb78a9cec580')
 | 
						|
        """
 | 
						|
        direct = (
 | 
						|
            type(target) is Oid
 | 
						|
            or (
 | 
						|
                all(c in hexdigits for c in target)
 | 
						|
                and GIT_OID_MINPREFIXLEN <= len(target) <= GIT_OID_HEXSZ))
 | 
						|
 | 
						|
        if direct:
 | 
						|
            return self.create_reference_direct(name, target, force)
 | 
						|
 | 
						|
        return self.create_reference_symbolic(name, target, force)
 | 
						|
 | 
						|
 | 
						|
    #
 | 
						|
    # Checkout
 | 
						|
    #
 | 
						|
    def checkout(self, refname=None, strategy=GIT_CHECKOUT_SAFE_CREATE):
 | 
						|
        """
 | 
						|
        Checkout the given reference using the given strategy, and update
 | 
						|
        the HEAD.
 | 
						|
        The reference may be a reference name or a Reference object.
 | 
						|
        The default strategy is GIT_CHECKOUT_SAFE_CREATE.
 | 
						|
 | 
						|
        To checkout from the HEAD, just pass 'HEAD'::
 | 
						|
 | 
						|
          >>> checkout('HEAD')
 | 
						|
 | 
						|
        If no reference is given, checkout from the index.
 | 
						|
 | 
						|
        """
 | 
						|
        # Case 1: Checkout index
 | 
						|
        if refname is None:
 | 
						|
            return self.checkout_index(strategy)
 | 
						|
 | 
						|
        # Case 2: Checkout head
 | 
						|
        if refname == 'HEAD':
 | 
						|
            return self.checkout_head(strategy)
 | 
						|
 | 
						|
        # Case 3: Reference
 | 
						|
        if type(refname) is Reference:
 | 
						|
            reference = refname
 | 
						|
            refname = refname.name
 | 
						|
        else:
 | 
						|
            reference = self.lookup_reference(refname)
 | 
						|
 | 
						|
        oid = reference.resolve().target
 | 
						|
        treeish = self[oid]
 | 
						|
        self.checkout_tree(treeish, strategy)
 | 
						|
        self.head = refname
 | 
						|
 | 
						|
 | 
						|
    #
 | 
						|
    # Diff
 | 
						|
    #
 | 
						|
    def diff(self, a=None, b=None, cached=False, flags=GIT_DIFF_NORMAL,
 | 
						|
             context_lines=3, interhunk_lines=0):
 | 
						|
        """
 | 
						|
        Show changes between the working tree and the index or a tree,
 | 
						|
        changes between the index and a tree, changes between two trees, or
 | 
						|
        changes between two blobs.
 | 
						|
 | 
						|
        Keyword arguments:
 | 
						|
 | 
						|
        cached
 | 
						|
            use staged changes instead of workdir
 | 
						|
 | 
						|
        flag
 | 
						|
            a GIT_DIFF_* constant
 | 
						|
 | 
						|
        context_lines
 | 
						|
            the number of unchanged lines that define the boundary
 | 
						|
            of a hunk (and to display before and after)
 | 
						|
 | 
						|
        interhunk_lines
 | 
						|
            the maximum number of unchanged lines between hunk
 | 
						|
            boundaries before the hunks will be merged into a one
 | 
						|
 | 
						|
        Examples::
 | 
						|
 | 
						|
          # Changes in the working tree not yet staged for the next commit
 | 
						|
          >>> diff()
 | 
						|
 | 
						|
          # Changes between the index and your last commit
 | 
						|
          >>> diff(cached=True)
 | 
						|
 | 
						|
          # Changes in the working tree since your last commit
 | 
						|
          >>> diff('HEAD')
 | 
						|
 | 
						|
          # Changes between commits
 | 
						|
          >>> t0 = revparse_single('HEAD')
 | 
						|
          >>> t1 = revparse_single('HEAD^')
 | 
						|
          >>> diff(t0, t1)
 | 
						|
          >>> diff('HEAD', 'HEAD^') # equivalent
 | 
						|
 | 
						|
        If you want to diff a tree against an empty tree, use the low level
 | 
						|
        API (Tree.diff_to_tree()) directly.
 | 
						|
        """
 | 
						|
 | 
						|
        def treeish_to_tree(obj):
 | 
						|
            try:
 | 
						|
                obj = self.revparse_single(obj)
 | 
						|
            except:
 | 
						|
                pass
 | 
						|
 | 
						|
            if isinstance(obj, Commit):
 | 
						|
                return obj.tree
 | 
						|
            elif isinstance(obj, Reference):
 | 
						|
                oid = obj.resolve().target
 | 
						|
                return self[oid]
 | 
						|
 | 
						|
        a = treeish_to_tree(a) or a
 | 
						|
        b = treeish_to_tree(b) or b
 | 
						|
 | 
						|
        opt_keys = ['flags', 'context_lines', 'interhunk_lines']
 | 
						|
        opt_values = [flags, context_lines, interhunk_lines]
 | 
						|
 | 
						|
        # Case 1: Diff tree to tree
 | 
						|
        if isinstance(a, Tree) and isinstance(b, Tree):
 | 
						|
            return a.diff_to_tree(b, **dict(zip(opt_keys, opt_values)))
 | 
						|
 | 
						|
        # Case 2: Index to workdir
 | 
						|
        elif a is None and b is None:
 | 
						|
            return self.index.diff_to_workdir(*opt_values)
 | 
						|
 | 
						|
        # Case 3: Diff tree to index or workdir
 | 
						|
        elif isinstance(a, Tree) and b is None:
 | 
						|
            if cached:
 | 
						|
                return a.diff_to_index(self.index, *opt_values)
 | 
						|
            else:
 | 
						|
                return a.diff_to_workdir(*opt_values)
 | 
						|
 | 
						|
        # Case 4: Diff blob to blob
 | 
						|
        if isinstance(a, Blob) and isinstance(b, Blob):
 | 
						|
            raise NotImplementedError('git_diff_blob_to_blob()')
 | 
						|
 | 
						|
        raise ValueError("Only blobs and treeish can be diffed")
 |