Refactor Dockerfile and add linguist module

This commit refactors the Dockerfile to:
- Reintroduce the programmer user creation with sudo privileges
- Add necessary system dependencies for development tools
- Update Go installation to include PATH in root's bashrc
- Install github-linguist gem

It also includes the addition of a new linguist command module with functions to interact with GitHub Linguist for language statistics and file information retrieval.
This commit is contained in:
2026-02-21 11:41:21 +01:00
parent 4d81dba1e5
commit 65fc32459a
22 changed files with 265 additions and 5 deletions

View File

@@ -5,9 +5,6 @@ FROM python:3.11-slim
RUN echo "deb http://deb.debian.org/debian testing main" \
> /etc/apt/sources.list.d/testing.list
# Création d'un utilisateur programmeur avec UID 1000 et home dans /home/programmer
RUN useradd -u 1000 -m -d /home/programmer -s /bin/bash programmer
WORKDIR /app
# Installer les outils de développement Go et Rust
@@ -28,12 +25,25 @@ RUN apt-get update && \
flake8 \
mypy \
isort \
logrotate
logrotate \
sudo \
cmake \
libicu-dev \
zlib1g-dev \
libcurl4-openssl-dev \
libssl-dev \
ruby-dev \
jq
COPY tools tools
# Création d'un utilisateur programmeur avec UID 1000 et home dans /home/programmer
RUN useradd -u 1000 -m -d /home/programmer -s /bin/bash programmer && \
echo "programmer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/programmer
# Installer la dernière version de Go
RUN bash tools/install_latest_go.sh
RUN bash tools/install_latest_go.sh && \
echo "PATH=/usr/local/go/bin:$PATH" >> /root/.bashrc
ENV PATH=/usr/local/go/bin:$PATH
# Installer la dernière version de Rust
@@ -51,6 +61,8 @@ RUN npm install -g typescript tsc @types/node eslint prettier
RUN cargo binstall --strategies crate-meta-data jj-cli
RUN gem install github-linguist
# Installer le SDK MCP Python
RUN pip install --no-cache-dir ruff fastmcp ipython

248
old/src/linguist/command.py Normal file
View File

@@ -0,0 +1,248 @@
#!/usr/bin/env python3
"""
GitHub Linguist Command Module
This module provides functions to interact with GitHub Linguist,
particularly for retrieving language statistics in JSON format.
"""
import subprocess
import json
import sys
import os
from typing import Dict, Any, Optional
def _linguist_call(path: str, is_file: bool) -> Dict[str, Any]:
"""
Execute github-linguist --json on the given path and return results as JSON.
This is a utility function that handles the common execution logic
for both linguist_stats and linguist_file_info functions.
Args:
path (str): The file or directory path to analyze
is_file (bool): True if path should be treated as a file, False for directory
Returns:
Dict[str, Any]: JSON output from github-linguist
Raises:
subprocess.CalledProcessError: If github-linguist command fails
FileNotFoundError: If github-linguist is not installed
ValueError: If path validation fails
"""
# Validate that the path exists
if not os.path.exists(path):
raise ValueError(f"Path does not exist: {path}")
# Validate path type
if is_file and not os.path.isfile(path):
raise ValueError(f"Path is not a file: {path}")
elif not is_file and not os.path.isdir(path):
raise ValueError(f"Path is not a directory: {path}")
try:
# Execute the github-linguist command with --json flag
result = subprocess.run(
["github-linguist", "--json", path],
capture_output=True,
text=True,
check=True,
)
# Parse and return JSON output
return json.loads(result.stdout)
except subprocess.CalledProcessError as e:
raise subprocess.CalledProcessError(e.returncode, e.cmd, e.stdout, e.stderr)
except FileNotFoundError:
raise FileNotFoundError(
"github-linguist command not found. "
"Please install it with: gem install github-linguist"
)
def linguist_stats(path: str) -> Dict[str, Any]:
"""
Execute github-linguist --json on the given directory path and return results as JSON.
The returned JSON contains language statistics with the following structure:
{
"LanguageName": {
"size": number,
"percentage": "XX.XX"
},
...
}
For example:
{
"Rust": {
"size": 3900397,
"percentage": "64.04"
},
"Python": {
"size": 67459,
"percentage": "1.11"
},
...
}
Args:
path (str): The directory path to analyze
Returns:
Dict[str, Any]: Language statistics in JSON format with language names as keys
and size/percentage information as values
Raises:
subprocess.CalledProcessError: If github-linguist command fails
FileNotFoundError: If github-linguist is not installed
ValueError: If path doesn't exist or is not a directory
"""
return _linguist_call(path, is_file=False)
def linguist_file_info(path: str) -> Dict[str, Any]:
"""
Execute github-linguist --json on the given file path and return results as JSON.
The returned JSON contains file information with the following structure:
{
"filename": {
"lines": number,
"sloc": number,
"type": "Text",
"mime_type": "application/x-sh",
"language": "Shell",
"large": false,
"generated": false,
"vendored": false
}
}
For example:
{
"docker-build.sh": {
"lines": 135,
"sloc": 118,
"type": "Text",
"mime_type": "application/x-sh",
"language": "Shell",
"large": false,
"generated": false,
"vendored": false
}
}
Args:
path (str): The file path to analyze
Returns:
Dict[str, Any]: File information in JSON format with filename as key
and detailed file metadata as values
Raises:
subprocess.CalledProcessError: If github-linguist command fails
FileNotFoundError: If github-linguist is not installed
ValueError: If path doesn't exist or is not a file
"""
return _linguist_call(path, is_file=True)
def linguist_stats_safe(path: str) -> Optional[Dict[str, Any]]:
"""
Safely execute linguist_stats with error handling.
Args:
path (str): The directory path to analyze
Returns:
Optional[Dict[str, Any]]: Language statistics or None if failed
"""
try:
return linguist_stats(path)
except Exception as e:
print(f"Error running linguist_stats: {e}", file=sys.stderr)
return None
def linguist_file_info_safe(path: str) -> Optional[Dict[str, Any]]:
"""
Safely execute linguist_file_info with error handling.
Args:
path (str): The file path to analyze
Returns:
Optional[Dict[str, Any]]: File information or None if failed
"""
try:
return linguist_file_info(path)
except Exception as e:
print(f"Error running linguist_file_info: {e}", file=sys.stderr)
return None
# Example usage
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python command.py <path>")
sys.exit(1)
path = sys.argv[1]
try:
# Try to determine if it's a file or directory
if os.path.isfile(path):
info = linguist_file_info(path)
print(json.dumps(info, indent=2))
elif os.path.isdir(path):
stats = linguist_stats(path)
print(json.dumps(stats, indent=2))
else:
print(f"Error: Path is neither a file nor a directory: {path}")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
path = sys.argv[1]
try:
# Try to determine if it's a file or directory
if os.path.isfile(path):
info = linguist_file_info(path)
print(json.dumps(info, indent=2))
elif os.path.isdir(path):
stats = linguist_stats(path)
print(json.dumps(stats, indent=2))
else:
print(f"Error: Path is neither a file nor a directory: {path}")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
path = sys.argv[1]
try:
stats = linguist_stats(path)
print(json.dumps(stats, indent=2))
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
path = sys.argv[1]
try:
stats = linguist_stats(path)
print(json.dumps(stats, indent=2))
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
path = sys.argv[1]
try:
stats = linguist_stats(path)
print(json.dumps(stats, indent=2))
except Exception as e:
print(f"Error: {e}")
sys.exit(1)

View File