506 lines
18 KiB
Bash
Executable File
506 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
||
# ============================================================
|
||
# setup-1c-repo.sh - Настройка Git-репозитория под выгрузку 1С (конфигуратор)
|
||
#
|
||
# Версия: 1.2.2
|
||
# Автор: Michael BAG <mk@p7net.ru>
|
||
# Репозиторий: https://git.p7net.ru/tools/git_man
|
||
#
|
||
# Платформы: Linux, macOS (на Windows используйте setup-1c-repo.ps1)
|
||
#
|
||
# Использование:
|
||
# ./setup-1c-repo.sh --path DIR [--help] [--version] [--dry-run] [--force]
|
||
# [--init] [--renormalize] [--no-gitignore]
|
||
# [--verbose] [--quiet]
|
||
#
|
||
# Описание:
|
||
# Включает локальные настройки Git в указанной папке (--path / --repo;
|
||
# обязательный параметр) для проектов с выгрузкой из конфигуратора 1С:
|
||
# - UTF-8 с BOM (как у конфигуратора; BOM хранится как часть содержимого)
|
||
# - CRLF в рабочей копии для *.bsl / *.xml и др. текстовых файлов выгрузки
|
||
# - корректное отображение кириллических путей (core.quotepath=false)
|
||
# - длинные пути (core.longpaths=true), Unicode на macOS
|
||
# - создаёт/обновляет .gitattributes и .gitignore
|
||
# ============================================================
|
||
|
||
set -e
|
||
|
||
SCRIPT_VERSION="1.2.2"
|
||
|
||
# ============================================================
|
||
# Справка
|
||
# ============================================================
|
||
show_help() {
|
||
cat << EOF
|
||
============================================================
|
||
📦 setup-1c-repo.sh v${SCRIPT_VERSION} — настройка репозитория под 1С
|
||
============================================================
|
||
|
||
ОПИСАНИЕ:
|
||
Настраивает локальный Git-репозиторий под выгрузку из
|
||
конфигуратора 1С (UTF-8 BOM + CRLF).
|
||
Путь к репозиторию обязателен: --path / --repo.
|
||
|
||
ИСПОЛЬЗОВАНИЕ:
|
||
./setup-1c-repo.sh --path DIR [ОПЦИИ]
|
||
|
||
ОПЦИИ:
|
||
--help, -h Показать эту справку
|
||
--version, -V Показать версию скрипта
|
||
--path DIR, --repo DIR
|
||
Папка репозитория для настройки (обязательно)
|
||
--dry-run Только показать, что будет сделано
|
||
--force, -f Перезаписать существующие .gitattributes / .gitignore
|
||
--init Выполнить git init, если папка ещё не репозиторий
|
||
(создаёт каталог, если его нет)
|
||
--renormalize После настройки: git add --renormalize .
|
||
--no-gitignore Не создавать/не менять .gitignore
|
||
--verbose, -v Подробный вывод
|
||
--quiet, -q Минимальный вывод (только ошибки)
|
||
|
||
ЧТО ДЕЛАЕТ:
|
||
1. Локальный git config (quotepath, encoding, autocrlf, longpaths, …)
|
||
2. Файл .gitattributes — EOL/binary для файлов выгрузки 1С
|
||
3. Файл .gitignore — типичные исключения (*.cf, *.cfe, …)
|
||
|
||
ПРИМЕРЫ:
|
||
./setup-1c-repo.sh --path /projects/uas_ep --force
|
||
./setup-1c-repo.sh --repo ../my-1c-dump --init
|
||
./setup-1c-repo.sh --path . --force --renormalize
|
||
./setup-1c-repo.sh --path /tmp/new-1c --init --dry-run
|
||
|
||
============================================================
|
||
EOF
|
||
exit 0
|
||
}
|
||
|
||
show_version() {
|
||
echo "setup-1c-repo.sh ${SCRIPT_VERSION}"
|
||
exit 0
|
||
}
|
||
|
||
# ============================================================
|
||
# Аргументы
|
||
# ============================================================
|
||
DRY_RUN=false
|
||
FORCE=false
|
||
VERBOSE=false
|
||
QUIET=false
|
||
DO_INIT=false
|
||
RENORMALIZE=false
|
||
NO_GITIGNORE=false
|
||
REPO_PATH=""
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--help|-h) show_help ;;
|
||
--version|-V) show_version ;;
|
||
--path|--repo)
|
||
if [ -z "${2:-}" ] || [[ "${2:-}" == -* ]]; then
|
||
echo -e "\033[0;31m❌ Для $1 укажите путь к папке репозитория\033[0m" >&2
|
||
exit 1
|
||
fi
|
||
REPO_PATH="$2"
|
||
shift 2
|
||
;;
|
||
--path=*|--repo=*)
|
||
REPO_PATH="${1#*=}"
|
||
if [ -z "$REPO_PATH" ]; then
|
||
echo -e "\033[0;31m❌ Пустой путь в $1\033[0m" >&2
|
||
exit 1
|
||
fi
|
||
shift
|
||
;;
|
||
--dry-run) DRY_RUN=true; shift ;;
|
||
--force|-f) FORCE=true; shift ;;
|
||
--init) DO_INIT=true; shift ;;
|
||
--renormalize) RENORMALIZE=true; shift ;;
|
||
--no-gitignore) NO_GITIGNORE=true; shift ;;
|
||
--verbose|-v) VERBOSE=true; shift ;;
|
||
--quiet|-q) QUIET=true; shift ;;
|
||
*)
|
||
echo -e "\033[0;31m❌ Неизвестная опция: $1\033[0m" >&2
|
||
echo " Используйте --help для справки" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# ============================================================
|
||
# Логирование
|
||
# ============================================================
|
||
if [ "$QUIET" != true ]; then
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'; CYAN='\033[0;36m'; MAGENTA='\033[0;35m'; NC='\033[0m'
|
||
else
|
||
RED=''; GREEN=''; YELLOW=''; BLUE=''; CYAN=''; MAGENTA=''; NC=''
|
||
fi
|
||
|
||
log_info() { [ "$QUIET" != true ] && echo -e "${CYAN}ℹ️ $1${NC}"; }
|
||
log_success() { [ "$QUIET" != true ] && echo -e "${GREEN}✅ $1${NC}"; }
|
||
log_warning() { [ "$QUIET" != true ] && echo -e "${YELLOW}⚠️ $1${NC}"; }
|
||
log_error() { echo -e "${RED}❌ $1${NC}" >&2; }
|
||
log_debug() { [ "$VERBOSE" = true ] && [ "$QUIET" != true ] && echo -e "${BLUE}🔍 $1${NC}"; }
|
||
log_step() { [ "$QUIET" != true ] && echo -e "${MAGENTA}▶ $1${NC}"; }
|
||
|
||
# ============================================================
|
||
# Определение ОС
|
||
# ============================================================
|
||
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
|
||
case "$OS_NAME" in
|
||
Darwin*) OS_KIND="macos" ;;
|
||
Linux*) OS_KIND="linux" ;;
|
||
MINGW*|MSYS*|CYGWIN*) OS_KIND="windows-bash" ;;
|
||
*) OS_KIND="unix" ;;
|
||
esac
|
||
|
||
# ============================================================
|
||
# Шаблоны файлов
|
||
# ============================================================
|
||
# Конфигуратор 1С выгружает текстовые файлы в UTF-8 с BOM и с CRLF.
|
||
# Git хранит BOM как часть содержимого; eol=crlf даёт CRLF в рабочей копии
|
||
# на любой ОС — совпадает с повторной выгрузкой из конфигуратора.
|
||
GITATTRIBUTES_CONTENT='# .gitattributes — выгрузка конфигуратора 1С (UTF-8 BOM + CRLF)
|
||
# Создано setup-1c-repo.sh (git_man). Не удаляйте без необходимости.
|
||
#
|
||
# Правило: текстовые файлы выгрузки — text + eol=crlf (рабочая копия = CRLF,
|
||
# в объекте Git нормализуется к LF). Бинарники — binary (без конвертации EOL).
|
||
|
||
* text=auto
|
||
|
||
# --- Текстовые файлы выгрузки конфигуратора ---
|
||
*.bsl text eol=crlf
|
||
*.os text eol=crlf
|
||
*.xml text eol=crlf
|
||
*.txt text eol=crlf
|
||
*.html text eol=crlf
|
||
*.htm text eol=crlf
|
||
*.xsd text eol=crlf
|
||
*.xslt text eol=crlf
|
||
*.xsl text eol=crlf
|
||
*.Form text eol=crlf
|
||
*.Module text eol=crlf
|
||
*.max text eol=crlf
|
||
|
||
# --- Служебные / документация репозитория (LF) ---
|
||
*.md text eol=lf
|
||
*.json text eol=lf
|
||
*.yml text eol=lf
|
||
*.yaml text eol=lf
|
||
*.sh text eol=lf
|
||
*.gitignore text eol=lf
|
||
*.gitattributes text eol=lf
|
||
.editorconfig text eol=lf
|
||
|
||
# --- Скрипты Windows ---
|
||
*.bat text eol=crlf
|
||
*.cmd text eol=crlf
|
||
*.ps1 text eol=crlf
|
||
|
||
# --- Бинарные артефакты 1С и медиа ---
|
||
*.bin binary
|
||
*.cf binary
|
||
*.cfe binary
|
||
*.cfu binary
|
||
*.epf binary
|
||
*.erf binary
|
||
*.axdt binary
|
||
*.addin binary
|
||
|
||
*.png binary
|
||
*.jpg binary
|
||
*.jpeg binary
|
||
*.gif binary
|
||
*.bmp binary
|
||
*.ico binary
|
||
*.webp binary
|
||
*.tif binary
|
||
*.tiff binary
|
||
*.svg -text
|
||
|
||
*.zip binary
|
||
*.rar binary
|
||
*.7z binary
|
||
*.gz binary
|
||
|
||
*.xls binary
|
||
*.xlsx binary
|
||
*.xlsm binary
|
||
*.doc binary
|
||
*.docx binary
|
||
*.pdf binary
|
||
*.rtf binary
|
||
|
||
*.ttf binary
|
||
*.otf binary
|
||
*.woff binary
|
||
*.woff2 binary
|
||
*.eot binary
|
||
'
|
||
|
||
GITIGNORE_CONTENT='# .gitignore — типовые исключения для проектов 1С (конфигуратор)
|
||
# Создано setup-1c-repo.sh (git_man)
|
||
|
||
# Бинарные выгрузки конфигурации / расширений / обработок
|
||
*.cf
|
||
*.cfe
|
||
*.cfu
|
||
*.epf
|
||
*.erf
|
||
|
||
# Временные и резервные
|
||
*.tmp
|
||
*.bak
|
||
*.~*
|
||
*~
|
||
*.old
|
||
*.orig
|
||
|
||
# Логи и дампы
|
||
*.log
|
||
*.lgp
|
||
*.lgf
|
||
|
||
# ОС
|
||
Thumbs.db
|
||
ehthumbs.db
|
||
Desktop.ini
|
||
desktop.ini
|
||
.DS_Store
|
||
.AppleDouble
|
||
.LSOverride
|
||
|
||
# IDE / редакторы
|
||
.vs/
|
||
.vscode/
|
||
.idea/
|
||
*.suo
|
||
*.user
|
||
*.userosscache
|
||
*.sln.docstates
|
||
|
||
# Отладка / кэш
|
||
Debug/
|
||
debug/
|
||
cache/
|
||
*.pfl
|
||
'
|
||
|
||
# ============================================================
|
||
# Целевой каталог репозитория
|
||
# ============================================================
|
||
resolve_repo_dir() {
|
||
local raw="$1"
|
||
if command -v realpath >/dev/null 2>&1; then
|
||
# realpath -m: путь может ещё не существовать (--init)
|
||
if realpath -m "$raw" >/dev/null 2>&1; then
|
||
realpath -m "$raw"
|
||
return 0
|
||
fi
|
||
fi
|
||
# Fallback без GNU realpath (macOS)
|
||
if [ -d "$raw" ]; then
|
||
(cd "$raw" && pwd -P)
|
||
return 0
|
||
fi
|
||
local parent base
|
||
parent=$(dirname "$raw")
|
||
base=$(basename "$raw")
|
||
if [ -d "$parent" ]; then
|
||
printf '%s/%s\n' "$(cd "$parent" && pwd -P)" "$base"
|
||
return 0
|
||
fi
|
||
printf '%s\n' "$raw"
|
||
}
|
||
|
||
if [ -z "$REPO_PATH" ]; then
|
||
log_error "Не указан путь к репозиторию"
|
||
echo " Обязательно: --path DIR или --repo DIR" >&2
|
||
echo " Справка: ./setup-1c-repo.sh --help" >&2
|
||
exit 1
|
||
fi
|
||
|
||
TARGET_DIR="$(resolve_repo_dir "$REPO_PATH")"
|
||
|
||
# ============================================================
|
||
# Проверка окружения
|
||
# ============================================================
|
||
log_step "Проверка окружения (ОС: ${OS_KIND})..."
|
||
log_info "Целевой каталог: $TARGET_DIR"
|
||
|
||
if ! command -v git >/dev/null 2>&1; then
|
||
log_error "Git не установлен"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -d "$TARGET_DIR" ]; then
|
||
if [ "$DO_INIT" = true ]; then
|
||
if [ "$DRY_RUN" = true ]; then
|
||
echo " [DRY-RUN] mkdir -p \"$TARGET_DIR\""
|
||
echo " [DRY-RUN] git -C \"$TARGET_DIR\" init"
|
||
else
|
||
mkdir -p "$TARGET_DIR"
|
||
log_success "Создан каталог: $TARGET_DIR"
|
||
git -C "$TARGET_DIR" init
|
||
log_success "Выполнен git init"
|
||
fi
|
||
else
|
||
log_error "Папка не существует: $TARGET_DIR"
|
||
echo " Укажите существующий путь или добавьте --init" >&2
|
||
exit 1
|
||
fi
|
||
else
|
||
if [ ! -d "$TARGET_DIR/.git" ] && [ ! -f "$TARGET_DIR/.git" ]; then
|
||
if [ "$DO_INIT" = true ]; then
|
||
if [ "$DRY_RUN" = true ]; then
|
||
echo " [DRY-RUN] git -C \"$TARGET_DIR\" init"
|
||
else
|
||
git -C "$TARGET_DIR" init
|
||
log_success "Выполнен git init"
|
||
fi
|
||
else
|
||
log_error "Папка не является Git-репозиторием: $TARGET_DIR"
|
||
echo " Укажите корень репозитория (--path) или добавьте --init" >&2
|
||
exit 1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
log_success "Окружение проверено"
|
||
|
||
# ============================================================
|
||
# Локальный git config
|
||
# ============================================================
|
||
set_local_config() {
|
||
local key="$1"
|
||
local value="$2"
|
||
if [ "$DRY_RUN" = true ]; then
|
||
echo " [DRY-RUN] git -C \"$TARGET_DIR\" config --local $key $value"
|
||
return 0
|
||
fi
|
||
git -C "$TARGET_DIR" config --local "$key" "$value"
|
||
log_debug "config $key=$value"
|
||
}
|
||
|
||
log_step "Локальные настройки Git..."
|
||
|
||
# Кириллические пути без \320\...
|
||
set_local_config core.quotepath false
|
||
# Длинные пути (особенно Windows / сетевые диски / глубокие деревья 1С)
|
||
set_local_config core.longpaths true
|
||
# Кодировки UI и коммитов
|
||
set_local_config gui.encoding utf-8
|
||
set_local_config i18n.commitEncoding utf-8
|
||
# EOL полностью через .gitattributes (без двойной конвертации)
|
||
set_local_config core.autocrlf false
|
||
set_local_config core.safecrlf warn
|
||
# Рекомендации 1С:ГитКонвертер для крупных деревьев метаданных
|
||
set_local_config diff.renames false
|
||
set_local_config diff.renameLimit 1
|
||
|
||
# macOS: NFD/NFC для имён файлов с кириллицей
|
||
if [ "$OS_KIND" = "macos" ]; then
|
||
set_local_config core.precomposeunicode true
|
||
log_info "macOS: core.precomposeunicode=true"
|
||
fi
|
||
|
||
if [ "$DRY_RUN" = true ]; then
|
||
log_info "Локальный git config (dry-run)"
|
||
else
|
||
log_success "Локальный git config применён"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Запись файла с бэкапом
|
||
# ============================================================
|
||
write_file_safe() {
|
||
local rel="$1"
|
||
local content="$2"
|
||
local label="$3"
|
||
local path="$TARGET_DIR/$rel"
|
||
|
||
if [ -f "$path" ] && [ "$FORCE" != true ]; then
|
||
log_warning "$label уже существует — пропуск (используйте --force)"
|
||
return 0
|
||
fi
|
||
|
||
if [ "$DRY_RUN" = true ]; then
|
||
if [ -f "$path" ]; then
|
||
echo " [DRY-RUN] перезаписать $path (бэкап ${path}.bak)"
|
||
else
|
||
echo " [DRY-RUN] создать $path"
|
||
fi
|
||
return 0
|
||
fi
|
||
|
||
if [ -f "$path" ]; then
|
||
cp -f "$path" "${path}.bak"
|
||
log_info "Бэкап: ${rel}.bak"
|
||
fi
|
||
|
||
# Пишем через printf, чтобы сохранить финальный перевод строки
|
||
printf '%s\n' "$content" > "$path"
|
||
log_success "Записан $rel"
|
||
}
|
||
|
||
log_step "Файл .gitattributes..."
|
||
write_file_safe ".gitattributes" "$GITATTRIBUTES_CONTENT" ".gitattributes"
|
||
|
||
if [ "$NO_GITIGNORE" != true ]; then
|
||
log_step "Файл .gitignore..."
|
||
write_file_safe ".gitignore" "$GITIGNORE_CONTENT" ".gitignore"
|
||
else
|
||
log_info "Пропуск .gitignore (--no-gitignore)"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Renormalize
|
||
# ============================================================
|
||
if [ "$RENORMALIZE" = true ]; then
|
||
log_step "Нормализация индекса (git add --renormalize .)..."
|
||
if [ "$DRY_RUN" = true ]; then
|
||
echo " [DRY-RUN] git -C \"$TARGET_DIR\" add --renormalize ."
|
||
else
|
||
git -C "$TARGET_DIR" add --renormalize .
|
||
log_success "Индекс перенормализован"
|
||
log_warning "Проверьте git status — возможны массовые изменения EOL"
|
||
fi
|
||
fi
|
||
|
||
# ============================================================
|
||
# Итог
|
||
# ============================================================
|
||
if [ "$QUIET" != true ]; then
|
||
echo ""
|
||
echo "============================================================"
|
||
echo -e "${CYAN}📊 Итог настройки под выгрузку конфигуратора 1С${NC}"
|
||
echo "============================================================"
|
||
echo " ОС: $OS_KIND ($OS_NAME)"
|
||
echo " Каталог: $TARGET_DIR"
|
||
echo " Encoding: UTF-8 (BOM сохраняется в содержимом файлов)"
|
||
echo " EOL (выгрузка): CRLF в рабочей копии (*.bsl, *.xml, …)"
|
||
echo " core.autocrlf: false (управляет .gitattributes)"
|
||
echo " core.quotepath: false"
|
||
if [ "$DRY_RUN" = true ]; then
|
||
echo ""
|
||
echo -e "${YELLOW}⚠️ Режим --dry-run: изменения НЕ применены${NC}"
|
||
else
|
||
echo ""
|
||
echo -e "${GREEN}✅ Готово${NC}"
|
||
echo ""
|
||
echo -e "${CYAN}Следующие шаги:${NC}"
|
||
echo " 1. cd \"$TARGET_DIR\" && git status"
|
||
echo " 2. git add .gitattributes .gitignore"
|
||
echo " 3. git commit -m \"Настройки Git для выгрузки конфигуратора 1С\""
|
||
if [ "$RENORMALIZE" != true ]; then
|
||
echo " 4. При необходимости нормализовать EOL:"
|
||
echo " ./setup-1c-repo.sh --path \"$TARGET_DIR\" --renormalize"
|
||
echo " или: git -C \"$TARGET_DIR\" add --renormalize ."
|
||
fi
|
||
fi
|
||
echo "============================================================"
|
||
echo ""
|
||
fi
|
||
|
||
exit 0
|