CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pygit2

Python bindings for libgit2 providing comprehensive Git repository operations and version control functionality.

Pending
Overview
Eval results
Files

remotes.mddocs/

Remote Operations

Git remote repository operations including fetching, pushing, and remote management. Handles authentication, transfer progress, and remote reference management for distributed Git workflows.

Capabilities

Remote Management

Manage connections to remote repositories with support for multiple remotes and various protocols.

class Remote:
    @property
    def name(self) -> str:
        """Remote name"""
    
    @property
    def url(self) -> str:
        """Remote URL"""
    
    @property
    def push_url(self) -> str:
        """Push URL (may differ from fetch URL)"""
    
    @property
    def refspecs(self) -> list[str]:
        """List of refspecs"""
    
    @property
    def fetch_refspecs(self) -> list[str]:
        """Fetch refspecs"""
    
    @property
    def push_refspecs(self) -> list[str]:
        """Push refspecs"""
    
    # Remote Operations
    def fetch(
        self,
        refspecs: list[str] = None,
        message: str = None,
        callbacks: 'RemoteCallbacks' = None,
        prune: int = None,
        update_fetchhead: bool = True
    ):
        """
        Fetch from remote repository.
        
        Parameters:
        - refspecs: Refspecs to fetch (None = use remote's refspecs)
        - message: Reflog message
        - callbacks: Remote operation callbacks
        - prune: Prune tracking branches (GIT_FETCH_PRUNE, GIT_FETCH_NO_PRUNE)
        - update_fetchhead: Update FETCH_HEAD
        """
    
    def push(
        self,
        refspecs: list[str],
        callbacks: 'RemoteCallbacks' = None
    ):
        """
        Push to remote repository.
        
        Parameters:
        - refspecs: Refspecs to push
        - callbacks: Remote operation callbacks
        """
    
    def upload(
        self,
        refspecs: list[str],
        callbacks: 'RemoteCallbacks' = None
    ):
        """Upload pack to remote (push without updating refs)"""
    
    def ls_remotes(self, callbacks: 'RemoteCallbacks' = None) -> list['RemoteHead']:
        """List remote references"""
    
    def prune(self, callbacks: 'RemoteCallbacks' = None):
        """Prune remote tracking branches"""
    
    def connect(self, direction: int, callbacks: 'RemoteCallbacks' = None):
        """Connect to remote"""
    
    def disconnect(self):
        """Disconnect from remote"""
    
    def download(self, refspecs: list[str] = None, callbacks: 'RemoteCallbacks' = None):
        """Download pack from remote"""
    
    def update_tips(self, callbacks: 'RemoteCallbacks' = None, message: str = None):
        """Update remote tracking references"""
    
    # Configuration
    def add_fetch_refspec(self, refspec: str):
        """Add fetch refspec"""
    
    def add_push_refspec(self, refspec: str):
        """Add push refspec"""
    
    def set_url(self, url: str):
        """Set remote URL"""
    
    def set_push_url(self, url: str):
        """Set push URL"""

# Remote Direction Constants  
GIT_DIRECTION_FETCH: int    # Fetch direction
GIT_DIRECTION_PUSH: int     # Push direction

# Fetch Prune Constants
GIT_FETCH_PRUNE_UNSPECIFIED: int  # Use config setting
GIT_FETCH_PRUNE: int               # Prune tracking branches
GIT_FETCH_NO_PRUNE: int            # Don't prune tracking branches

Remote Collection

Manage multiple remotes in a repository.

class RemoteCollection:
    def create(self, name: str, url: str) -> Remote:
        """Create new remote"""
    
    def delete(self, name: str):
        """Delete remote"""
    
    def rename(self, name: str, new_name: str) -> list[str]:
        """
        Rename remote.
        
        Returns:
        List of non-default refspecs that couldn't be renamed
        """
    
    def set_url(self, name: str, url: str):
        """Set remote URL"""
    
    def set_push_url(self, name: str, url: str):
        """Set remote push URL"""
    
    def add_fetch_refspec(self, name: str, refspec: str):
        """Add fetch refspec to remote"""
    
    def add_push_refspec(self, name: str, refspec: str):
        """Add push refspec to remote"""
    
    def get(self, name: str) -> Remote:
        """Get remote by name"""
    
    def __getitem__(self, name: str) -> Remote:
        """Get remote by name"""
    
    def __contains__(self, name: str) -> bool:
        """Check if remote exists"""
    
    def __iter__(self):
        """Iterate over remotes"""
    
    def __len__(self) -> int:
        """Number of remotes"""

# Repository remote access
class Repository:
    @property
    def remotes(self) -> RemoteCollection:
        """Repository remotes collection"""

Remote References

Information about references on remote repositories.

class RemoteHead:
    @property
    def name(self) -> str:
        """Reference name"""
    
    @property
    def oid(self) -> Oid:
        """Reference target OID"""
    
    @property
    def local_oid(self) -> Oid:
        """Local OID for this reference"""
    
    @property
    def is_local(self) -> bool:
        """True if reference exists locally"""

class PushUpdate:
    @property
    def src_refname(self) -> str:
        """Source reference name"""
    
    @property
    def dst_refname(self) -> str:
        """Destination reference name"""
    
    @property
    def src(self) -> Oid:
        """Source OID"""
    
    @property
    def dst(self) -> Oid:
        """Destination OID"""

Transfer Progress

Track progress of remote operations like fetch and push.

class TransferProgress:
    @property
    def total_objects(self) -> int:
        """Total objects to transfer"""
    
    @property
    def indexed_objects(self) -> int:
        """Objects indexed so far"""
    
    @property
    def received_objects(self) -> int:
        """Objects received so far"""
    
    @property
    def local_objects(self) -> int:
        """Local objects"""
    
    @property
    def total_deltas(self) -> int:
        """Total deltas to process"""
    
    @property
    def indexed_deltas(self) -> int:
        """Deltas indexed so far"""
    
    @property
    def received_bytes(self) -> int:
        """Bytes received"""

Remote Callbacks

Callback interface for handling remote operations, authentication, and progress.

class RemoteCallbacks:
    def credentials(
        self,
        url: str,
        username_from_url: str,
        allowed_types: int
    ):
        """
        Provide credentials for authentication.
        
        Parameters:
        - url: Remote URL
        - username_from_url: Username from URL
        - allowed_types: Credential types allowed
        
        Returns:
        Credential object or None
        """
        return None
    
    def progress(self, stats: TransferProgress) -> bool:
        """
        Report transfer progress.
        
        Parameters:
        - stats: Transfer progress information
        
        Returns:
        True to continue, False to cancel
        """
        return True
    
    def update_tips(
        self,
        refname: str,
        old: Oid,
        new: Oid
    ) -> int:
        """
        Called when updating references.
        
        Parameters:
        - refname: Reference name
        - old: Old OID
        - new: New OID
        
        Returns:
        0 for success, non-zero for error
        """
        return 0
    
    def completion(self, completion_type: int) -> int:
        """
        Called on operation completion.
        
        Parameters:
        - completion_type: Type of completed operation
        
        Returns:
        0 for success
        """
        return 0
    
    def push_update_reference(
        self,
        refname: str,
        message: str
    ) -> int:
        """
        Called for each push update.
        
        Parameters:
        - refname: Reference name
        - message: Error message (if any)
        
        Returns:
        0 for success
        """
        return 0
    
    def pack_progress(
        self,
        stage: int,
        current: int,
        total: int
    ) -> int:
        """Report pack progress"""
        return 0
    
    def sideband_progress(self, string: str) -> int:
        """Handle sideband progress messages"""
        return 0
    
    def certificate_check(
        self,
        certificate,
        valid: bool,
        host: str
    ) -> bool:
        """
        Check server certificate.
        
        Returns:
        True to accept certificate
        """
        return valid

Refspecs

Refspec objects define how references are mapped between local and remote repositories.

class Refspec:
    @property
    def src(self) -> str:
        """Source reference pattern"""
    
    @property
    def dst(self) -> str:
        """Destination reference pattern"""
    
    @property
    def force(self) -> bool:
        """True if refspec forces update"""
    
    @property
    def string(self) -> str:
        """Refspec string representation"""
    
    @property
    def direction(self) -> int:
        """Refspec direction (fetch or push)"""
    
    def src_matches(self, refname: str) -> bool:
        """Check if refname matches source pattern"""
    
    def dst_matches(self, refname: str) -> bool:
        """Check if refname matches destination pattern"""
    
    def transform(self, refname: str) -> str:
        """Transform refname using refspec"""
    
    def rtransform(self, refname: str) -> str:
        """Reverse transform refname using refspec"""

Usage Examples

Basic Remote Operations

import pygit2

repo = pygit2.Repository('/path/to/repo')

# List remotes
print("Remotes:")
for remote in repo.remotes:
    print(f"  {remote.name}: {remote.url}")

# Add new remote
origin = repo.remotes.create('origin', 'https://github.com/user/repo.git')

# Get existing remote
origin = repo.remotes['origin']
print(f"Origin URL: {origin.url}")

# Set different push URL
origin.set_push_url('git@github.com:user/repo.git')

Fetching from Remote

# Simple fetch
origin = repo.remotes['origin']
origin.fetch()

# Fetch with custom refspecs
origin.fetch(['refs/heads/*:refs/remotes/origin/*'])

# Fetch with callbacks
class FetchCallbacks(pygit2.RemoteCallbacks):
    def progress(self, stats):
        print(f"Received {stats.received_objects}/{stats.total_objects} objects")
        return True
    
    def credentials(self, url, username_from_url, allowed_types):
        if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:
            return pygit2.Keypair('git', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa', '')
        return None

callbacks = FetchCallbacks()
origin.fetch(callbacks=callbacks)

Pushing to Remote

# Push specific branch
origin.push(['refs/heads/main:refs/heads/main'])

# Push all branches
origin.push(['refs/heads/*:refs/heads/*'])

# Push with callbacks
class PushCallbacks(pygit2.RemoteCallbacks):
    def push_update_reference(self, refname, message):
        if message:
            print(f"Error pushing {refname}: {message}")
            return -1
        else:
            print(f"Successfully pushed {refname}")
        return 0
    
    def credentials(self, url, username_from_url, allowed_types):
        return pygit2.UserPass('username', 'password')

callbacks = PushCallbacks()
origin.push(['refs/heads/feature:refs/heads/feature'], callbacks=callbacks)

Listing Remote References

# List remote references
remote_refs = origin.ls_remotes()
print("Remote references:")
for ref in remote_refs:
    print(f"  {ref.name}: {ref.oid}")
    if ref.is_local:
        print(f"    (local: {ref.local_oid})")

Advanced Remote Operations

# Clone with custom callbacks
class CloneCallbacks(pygit2.RemoteCallbacks):
    def progress(self, stats):
        if stats.total_objects > 0:
            percent = (stats.received_objects * 100) // stats.total_objects
            print(f"Cloning: {percent}% ({stats.received_objects}/{stats.total_objects})")
        return True
    
    def credentials(self, url, username_from_url, allowed_types):
        if 'github.com' in url:
            if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:
                return pygit2.Keypair('git', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa', '')
        return None

callbacks = CloneCallbacks()
repo = pygit2.clone_repository(
    'git@github.com:user/repo.git',
    '/local/path',
    callbacks=callbacks
)

# Prune remote tracking branches
origin.prune()

# Update remote URL
repo.remotes.set_url('origin', 'https://new-url.com/repo.git')

# Add additional fetch refspec
origin.add_fetch_refspec('refs/pull/*/head:refs/remotes/origin/pr/*')

Working with Refspecs

# Examine refspecs
for refspec_str in origin.fetch_refspecs:
    refspec = pygit2.Refspec(refspec_str)
    print(f"Refspec: {refspec.string}")
    print(f"  Source: {refspec.src}")
    print(f"  Destination: {refspec.dst}")
    print(f"  Force: {refspec.force}")
    
    # Test refspec matching
    if refspec.src_matches('refs/heads/main'):
        transformed = refspec.transform('refs/heads/main')
        print(f"  'refs/heads/main' -> '{transformed}'")

# Add custom refspecs
origin.add_fetch_refspec('refs/tags/*:refs/tags/*')
origin.add_push_refspec('refs/heads/main:refs/heads/master')

Authentication Examples

# SSH key authentication
class SSHCallbacks(pygit2.RemoteCallbacks):
    def credentials(self, url, username_from_url, allowed_types):
        if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:
            return pygit2.Keypair(
                'git',
                '/home/user/.ssh/id_rsa.pub',
                '/home/user/.ssh/id_rsa',
                'passphrase'
            )
        return None

# Username/password authentication  
class HTTPSCallbacks(pygit2.RemoteCallbacks):
    def credentials(self, url, username_from_url, allowed_types):
        if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:
            return pygit2.UserPass('username', 'personal_access_token')
        return None

# SSH agent authentication
class AgentCallbacks(pygit2.RemoteCallbacks):
    def credentials(self, url, username_from_url, allowed_types):
        if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:
            return pygit2.KeypairFromAgent('git')
        return None

Progress Monitoring

class DetailedCallbacks(pygit2.RemoteCallbacks):
    def __init__(self):
        self.total_bytes = 0
        self.start_time = time.time()
    
    def progress(self, stats):
        # Calculate transfer rate
        elapsed = time.time() - self.start_time
        if elapsed > 0:
            rate = stats.received_bytes / elapsed / 1024  # KB/s
        else:
            rate = 0
        
        print(f"\rObjects: {stats.received_objects}/{stats.total_objects} "
              f"Deltas: {stats.indexed_deltas}/{stats.total_deltas} "
              f"Rate: {rate:.1f} KB/s", end='')
        
        return True
    
    def sideband_progress(self, string):
        print(f"Remote: {string.strip()}")
        return 0

callbacks = DetailedCallbacks()
origin.fetch(callbacks=callbacks)
print()  # New line after progress

Install with Tessl CLI

npx tessl i tessl/pypi-pygit2

docs

advanced.md

auth.md

config.md

diff.md

index.md

objects.md

references.md

remotes.md

repository.md

staging.md

tile.json