CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dulwich

Pure Python implementation of the Git version control system providing comprehensive access to Git repositories without requiring the Git command-line tool

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration Management

Comprehensive Git configuration file parsing and manipulation supporting repository, user, and system-level configuration with hierarchical stacking, type conversion, multi-value support, URL rewriting, and advanced pattern matching for includeIf directives.

Capabilities

Configuration Classes

Classes for reading and writing Git configuration files with hierarchical support.

class Config:
    """Abstract base class for Git configuration."""
    
    def get(self, section: SectionLike, name: NameLike) -> Value:
        """
        Get configuration value.
        
        Args:
            section: Section name or tuple with section and optional subsection
            name: Configuration key name
            
        Returns:
            Configuration value as bytes
            
        Raises:
            KeyError: If the value is not set
        """
    
    def get_multivar(self, section: SectionLike, name: NameLike) -> Iterator[Value]:
        """
        Get multiple values for a configuration key.
        
        Args:
            section: Section name or tuple with section and optional subsection
            name: Configuration key name
            
        Returns:
            Iterator over configuration values
            
        Raises:
            KeyError: If the value is not set
        """
        
    def get_boolean(
        self, 
        section: SectionLike, 
        name: NameLike, 
        default: Optional[bool] = None
    ) -> Optional[bool]:
        """
        Get configuration value as boolean.
        
        Args:
            section: Section name or tuple with section and optional subsection
            name: Configuration key name
            default: Default value if not found
            
        Returns:
            Boolean value or default
            
        Raises:
            ValueError: If value is not a valid boolean
        """
    
    def set(
        self, 
        section: SectionLike, 
        name: NameLike, 
        value: Union[ValueLike, bool]
    ) -> None:
        """
        Set configuration value.
        
        Args:
            section: Section name or tuple with section and optional subsection
            name: Configuration key name
            value: Value to set
        """
    
    def items(self, section: SectionLike) -> Iterator[Tuple[Name, Value]]:
        """
        Iterate over items in a configuration section.
        
        Args:
            section: Section name or tuple with section and optional subsection
            
        Yields:
            Tuples of (name, value) pairs
        """
        
    def sections(self) -> Iterator[Section]:
        """
        Iterate over configuration sections.
        
        Returns:
            Iterator over section tuples
        """
        
    def has_section(self, name: Section) -> bool:
        """
        Check if a section exists.
        
        Args:
            name: Section name to check
            
        Returns:
            True if section exists
        """

class ConfigDict(Config):
    """Git configuration stored in a dictionary.
    
    Provides in-memory configuration storage with case-insensitive
    section names and support for multi-valued configuration keys.
    """
    
    def __init__(
        self, 
        values: Optional[MutableMapping[Section, MutableMapping[Name, Value]]] = None,
        encoding: Optional[str] = None
    ):
        """
        Initialize dictionary-based configuration.
        
        Args:
            values: Initial configuration values
            encoding: Text encoding (defaults to system default)
        """
        
    def __getitem__(self, key: Section) -> CaseInsensitiveOrderedMultiDict[Name, Value]:
        """Get section by name."""
        
    def __setitem__(self, key: Section, value: MutableMapping[Name, Value]) -> None:
        """Set section by name."""
        
    def __delitem__(self, key: Section) -> None:
        """Delete section by name."""
        
    def __iter__(self) -> Iterator[Section]:
        """Iterate over section names."""
        
    def __len__(self) -> int:
        """Number of sections."""
        
    def keys(self) -> KeysView[Section]:
        """Get section names."""

class ConfigFile(ConfigDict):
    """File-based configuration implementation.
    
    Reads and writes Git configuration files with proper parsing
    of sections, subsections, and multi-line values.
    """
    
    def __init__(
        self, 
        filename: Optional[str] = None, 
        file: Optional[BinaryIO] = None, 
        encoding: Optional[str] = None
    ):
        """
        Initialize file-based configuration.
        
        Args:
            filename: Path to configuration file
            file: File-like object to read from
            encoding: Text encoding (defaults to UTF-8)
        """
        
    @classmethod
    def from_path(cls, path: str) -> "ConfigFile":
        """
        Create ConfigFile from file path.
        
        Args:
            path: Path to configuration file
            
        Returns:
            ConfigFile instance
        """
        
    @classmethod  
    def from_file(cls, f: BinaryIO) -> "ConfigFile":
        """
        Create ConfigFile from file object.
        
        Args:
            f: File-like object to read from
            
        Returns:
            ConfigFile instance
        """
    
    def write_to_path(self, path: str) -> None:
        """
        Write configuration to file path.
        
        Args:
            path: Output file path
        """
    
    def write_to_file(self, f: BinaryIO) -> None:
        """
        Write configuration to file-like object.
        
        Args:
            f: File-like object to write to
        """
        
    def write(self) -> None:
        """
        Write configuration back to original file.
        """

class StackedConfig(Config):
    """Configuration which reads from multiple config files.
    
    Provides layered configuration where values are looked up
    in order from multiple configuration sources (local, global, system).
    """
    
    def __init__(
        self, 
        backends: List[ConfigFile], 
        writable: Optional[ConfigFile] = None
    ):
        """
        Initialize stacked configuration.
        
        Args:
            backends: List of configuration files (searched in order)
            writable: Configuration file for write operations
        """
        
    @classmethod
    def default(cls) -> "StackedConfig":
        """
        Create default stacked configuration.
        
        Returns:
            StackedConfig with system, global, and user configurations
        """
    
    @classmethod
    def default_backends(cls) -> List[ConfigFile]:
        """
        Get default configuration backends.
        
        Searches for configuration files in Git's standard locations:
        - User config: ~/.gitconfig or $XDG_CONFIG_HOME/git/config
        - System config: /etc/gitconfig (Unix) or system paths (Windows)
        
        Respects GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM, and GIT_CONFIG_NOSYSTEM
        environment variables.
        
        Returns:
            List of ConfigFile objects for found configuration files
        """

Utility Classes

Helper classes for configuration file handling.

class CaseInsensitiveOrderedMultiDict:
    """Case-insensitive dictionary supporting multiple values per key."""
    
    def __init__(self): ...
    
    def __getitem__(self, key: str) -> Any: ...
    def __setitem__(self, key: str, value: Any) -> None: ...
    def __contains__(self, key: str) -> bool: ...
    
    def get(self, key: str, default=None) -> Any:
        """Get value with default."""
    
    def getlist(self, key: str) -> List[Any]:
        """Get all values for key as list."""
    
    def items(self) -> Iterator[Tuple[str, Any]]:
        """Iterate over key-value pairs."""

Submodule Configuration

Functions for reading and parsing Git submodule configuration.

def read_submodules(config_file) -> Iterator[Tuple[bytes, bytes, bytes]]:
    """
    Read submodule configuration from .gitmodules file.
    
    Args:
        config_file: Configuration file object
        
    Yields:
        Tuples of (path, name, url)
    """

def parse_submodules(config: Config) -> Dict[bytes, Dict[bytes, bytes]]:
    """
    Parse submodule configuration into structured format.
    
    Args:
        config: Configuration object
        
    Returns:
        Dictionary mapping submodule names to their configuration
    """

URL Rewriting

Functions for handling Git URL rewriting configuration (insteadOf).

def iter_instead_of(config: Config, push: bool = False) -> Iterator[Tuple[bytes, bytes]]:
    """
    Iterate over URL rewriting rules.
    
    Args:
        config: Configuration object
        push: Whether to get pushInsteadOf rules
        
    Yields:
        Tuples of (original_prefix, replacement_prefix)
    """

def apply_instead_of(config: Config, url: bytes, push: bool = False) -> bytes:
    """
    Apply URL rewriting rules to a URL.
    
    Args:
        config: Configuration object
        url: Original URL
        push: Whether to apply pushInsteadOf rules
        
    Returns:
        Rewritten URL
    """

Pattern Matching

Functions for Git configuration pattern matching.

def match_glob_pattern(pattern: str, path: str) -> bool:
    """
    Match path against Git glob pattern.
    
    Args:
        pattern: Glob pattern (supports *, ?, [])
        path: Path to match
        
    Returns:
        True if path matches pattern
    """

Usage Examples

Basic Configuration Operations

from dulwich.config import ConfigFile

# Read repository configuration
config = ConfigFile.from_path('.git/config')

# Get configuration values
user_name = config.get(('user',), 'name')
user_email = config.get(('user',), 'email')
print(f"User: {user_name.decode()} <{user_email.decode()}>")

# Set configuration values
config.set(('user',), 'name', 'John Doe')
config.set(('user',), 'email', 'john@example.com')

# Work with sections
for section in config.sections():
    print(f"Section: {section}")
    for name, value in config.items(section):
        print(f"  {name.decode()}: {value.decode()}")

# Write changes back to file
config.write()  # Writes to original file
# Or write to different path
config.write_to_path('/tmp/config-backup')

Stacked Configuration

from dulwich.config import ConfigFile, StackedConfig

# Create stacked configuration (system -> global -> local)
system_config = ConfigFile('/etc/gitconfig')
global_config = ConfigFile('~/.gitconfig')
local_config = ConfigFile('.git/config')

stacked = StackedConfig([system_config, global_config, local_config], 
                       writable=local_config)

# Get value (searches from local to system)
core_editor = stacked.get(b'core', b'editor')

# Set value (writes to writable backend)
stacked.set(b'user', b'name', b'Jane Doe'.encode())

Submodule Configuration

from dulwich.config import ConfigFile, parse_submodules

# Read .gitmodules file
gitmodules = ConfigFile('.gitmodules')

# Parse submodule configuration
submodules = parse_submodules(gitmodules)

for submodule_name, submodule_config in submodules.items():
    path = submodule_config[b'path']
    url = submodule_config[b'url']
    print(f"Submodule {submodule_name.decode()}: {path.decode()} -> {url.decode()}")

URL Rewriting

from dulwich.config import ConfigFile, apply_instead_of

# Configure URL rewriting
config = ConfigFile('.git/config')
config.set(b'url', b'https://github.com/', b'git@github.com:')
config.set(b'url "https://github.com/"', b'insteadOf', b'gh:')

# Apply rewriting
original_url = b'gh:user/repo.git'
rewritten_url = apply_instead_of(config, original_url)
print(f"Rewritten: {original_url.decode()} -> {rewritten_url.decode()}")

Multi-value Configuration

from dulwich.config import ConfigFile

config = ConfigFile('.git/config')

# Set multiple values for same key
config.set(b'remote "origin"', b'fetch', b'+refs/heads/*:refs/remotes/origin/*')
config.set(b'remote "origin"', b'fetch', b'+refs/pull/*/head:refs/remotes/origin/pr/*')

# Get all values
fetch_specs = config.get_multivar(b'remote "origin"', b'fetch')
for spec in fetch_specs:
    print(f"Fetch spec: {spec.decode()}")

Install with Tessl CLI

npx tessl i tessl/pypi-dulwich

docs

cli.md

clients.md

configuration.md

diff-merge.md

index-management.md

index.md

object-storage.md

objects.md

pack-files.md

porcelain.md

references.md

repository.md

tile.json