Compare commits

...

9 commits

Author SHA1 Message Date
d58ab81fd8
Автоматизирован процесс получения версии программы из исходнго файла при сборке в пакет:
- Копирование source/snag/version_.d в source/snag/version_.d.bak и каждый раз восстанавливается оригинальный файл при сборке через CMake
- Добавлена параметризорванная возможность включения hash в версионирование по флагу GIT_HASH_VERSION
2025-06-02 11:08:50 +03:00
4474cc5b7c
Полная версия программы при сборке в Cmake 2025-06-02 01:04:07 +03:00
d2308bee16
Merge branch 'develop' into debian 2025-06-02 01:01:10 +03:00
80ace62abf
Указан явный путь к рабочей директории проекта при вызове команды git, так как вызов snag из под не рабочей директории не выполнял некоторые операции на старых версиях git 2025-06-02 00:59:27 +03:00
c0ed8e6935
Merge branch 'develop' into debian 2025-06-02 00:28:48 +03:00
ee41d5f96d
Смена относительного пути проекта на абсолютный, который исправляет проблему при работе с проектом во время добавления/восстановления 2025-06-02 00:26:38 +03:00
e43b792df8
Добавлена информация для фидбэка при возникновении непредвиденных ошибок 2025-05-30 19:11:31 +03:00
552b635b59
- Корректный вывод пути файла/директории при вызове status
- Добавлен вывод секунд при вызове info
2025-05-30 19:07:09 +03:00
8a64320214
В библиотеку добавлена функция разбития строки по первому символу пробела 2025-05-30 19:06:29 +03:00
10 changed files with 78 additions and 47 deletions

View file

@ -1,18 +1,15 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.14)
project(snag) project(snag)
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 1)
set(PROJECT_VERSION_PATCH 0)
string(TIMESTAMP PROJECT_VERSION_BUILD "%y%j.%H%M")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(snag_git) include(snag_version)
string(TIMESTAMP PROJECT_VERSION_BUILD "%y%j.%H%M")
if(GIT_HASH_VERSION)
message(STATUS "GIT_HASH_VERSION is set")
include(snag_git)
endif()
include(snag_platforms) include(snag_platforms)
set(PROJECT_VERSION_SUFFIX "-${GIT_VERSION_SUFFIX}")
# Overwrite suffix for Release or Release Candidate builds
set(PROJECT_VERSION_SUFFIX "-alpha.1")
set(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
if(CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
set(BUILD_TYPE ${CMAKE_BUILD_TYPE}) set(BUILD_TYPE ${CMAKE_BUILD_TYPE})
@ -27,7 +24,7 @@ message(STATUS "PROJECT_VERSION_DISPLAY: ${PROJECT_VERSION_DISPLAY}")
message(STATUS "") message(STATUS "")
# Deb package # Deb package
set(DEB_PACKAGE_VERSION "${PROJECT_VERSION_DISPLAY}${PROJECT_VERSION_SUFFIX}") set(DEB_PACKAGE_VERSION "${PROJECT_VERSION_DISPLAY}${PROJECT_VERSION_SUFFIX}${GIT_VERSION_SUFFIX}")
if(PROJECT_VERSION_CODENAME) if(PROJECT_VERSION_CODENAME)
set(DEB_PACKAGE_VERSION "${DEB_PACKAGE_VERSION}-${PROJECT_VERSION_CODENAME}") set(DEB_PACKAGE_VERSION "${DEB_PACKAGE_VERSION}-${PROJECT_VERSION_CODENAME}")
endif() endif()

View file

@ -1,24 +1,20 @@
cmake_minimum_required(VERSION 3.6) cmake_minimum_required(VERSION 3.6)
if(DEFINED ENV{CI_COMMIT_BRANCH}) find_package(Git)
string(REGEX REPLACE ".*/" "" GIT_BRANCH $ENV{CI_COMMIT_BRANCH})
string(REPLACE "_" "-" GIT_BRANCH ${GIT_BRANCH}) if(GIT_FOUND)
if(NOT GIT_BRANCH STREQUAL "stable") # Получаем короткий хэш текущего коммита
set(GIT_VERSION_SUFFIX "${GIT_BRANCH}-") execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_SHORT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Проверяем, успешно ли получен хэш
if(GIT_SHORT_HASH)
message(STATUS "Git short hash: ${GIT_SHORT_HASH}")
set(GIT_VERSION_SUFFIX "-${GIT_SHORT_HASH}")
else() else()
set(GIT_VERSION_SUFFIX "") message(WARNING "Failed to retrieve Git short hash")
endif() endif()
else()
set(GIT_BRANCH "dev")
set(GIT_VERSION_SUFFIX "${GIT_BRANCH}-")
endif() endif()
if(DEFINED ENV{CI_COMMIT_SHORT_SHA})
set(GIT_TAG $ENV{CI_COMMIT_SHORT_SHA})
else()
set(GIT_TAG "0000000")
endif()
set(GIT_VERSION_SUFFIX "${GIT_VERSION_SUFFIX}${GIT_TAG}")
MESSAGE(STATUS "GIT_VERSION_SUFFIX: ${GIT_VERSION_SUFFIX}")
MESSAGE(STATUS "")

28
cmake/snag_version.cmake Normal file
View file

@ -0,0 +1,28 @@
cmake_minimum_required (VERSION 3.6)
# Сохраняем копию файла с версией программы и каждый раз обновляем при конфигуре через Cmake
if(EXISTS "${CMAKE_SOURCE_DIR}/source/snag/version_.d.bak")
configure_file(
"${CMAKE_SOURCE_DIR}/source/snag/version_.d.bak"
"${CMAKE_SOURCE_DIR}/source/snag/version_.d"
COPYONLY
)
else()
configure_file(
"${CMAKE_SOURCE_DIR}/source/snag/version_.d"
"${CMAKE_SOURCE_DIR}/source/snag/version_.d.bak"
COPYONLY
)
endif()
# Чтение файла version_.d
file(READ "${CMAKE_SOURCE_DIR}/source/snag/version_.d" VERSION_FILE_CONTENT)
# Извлечение строки версии (например, "0.1.0-alpha.1")
string(REGEX MATCH "snagVersion = \"([0-9]+)\\.([0-9]+)\\.([0-9]+)([^\"]*)\"" _ ${VERSION_FILE_CONTENT})
# Установка переменных для мажорной, минорной, патч-версии и суффикса
set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1})
set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2})
set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3})
set(PROJECT_VERSION_SUFFIX ${CMAKE_MATCH_4})

View file

@ -1,6 +1,6 @@
# Сборка из под Debian # Сборка из под Debian
``` ```
cmake . cmake . -DGIT_HASH_VERSION=ON
dpkg-buildpackage -us -uc -nc dpkg-buildpackage -us -uc -nc
``` ```

2
debian/rules vendored
View file

@ -8,7 +8,7 @@ DEST_DIR = $(DEBIAN_DIR)/snag
dh $@ $(BUILD_SYSTEM) dh $@ $(BUILD_SYSTEM)
override_dh_auto_configure: override_dh_auto_configure:
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DGIT_HASH_VERSION=ON
override_dh_auto_build: override_dh_auto_build:
cmake --build build cmake --build build

View file

@ -237,7 +237,9 @@ int main(string[] args)
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (Exception e) { } catch (Exception e) {
writeln( writeln(
"AN UNEXPECTED ERROR HAS OCCURRED! PLEASE REPORT IT TO THE AUTHOR OF THE SNAG!\n\n", "AN UNEXPECTED ERROR HAS OCCURRED!\n",
"PLEASE REPORT IT TO THE AUTHOR OF THE SNAG: ",
"alexander@zhirov.kz (Alexander Zhirov)\n\n",
e e
); );
return EXIT_FAILURE; return EXIT_FAILURE;

View file

@ -22,8 +22,8 @@ class Snag {
this(SnagConfig config) { this(SnagConfig config) {
_baseCommand = format( _baseCommand = format(
"git --git-dir=%s --work-tree=%s", "git -C %s --git-dir=%s --work-tree=%s",
config.git, config.project config.project, config.git, config.project
).split(); ).split();
_config = config; _config = config;
@ -131,7 +131,7 @@ class Snag {
} }
writeln("The following list of files requires backup:"); writeln("The following list of files requires backup:");
result.output.split('\n')[0..$-1].map!(e => result.output.split('\n')[0..$-1].map!(e =>
e.strip.split e.strip.splitByFirstSpace
).each!(e => ).each!(e =>
writefln("\t%s\t/%s", gitStatus(e[0], true), e[1]) writefln("\t%s\t/%s", gitStatus(e[0], true), e[1])
); );
@ -158,7 +158,7 @@ class Snag {
result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]); result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]);
if (result.status == 128) { if (result.status == 128) {
// Если это самый первый коммит после инициализации репозитория // Если это самый первый коммит после инициализации репозитория
git(["add", "."], "Failed to prepare files for archiving"); git(["add", _config.project], "Failed to prepare files for archiving");
git(["commit", "-m"] ~ message, "Failed to create a snapshot"); git(["commit", "-m"] ~ message, "Failed to create a snapshot");
newSnapshot = git( newSnapshot = git(
["rev-parse", "--short", "HEAD"], ["rev-parse", "--short", "HEAD"],
@ -197,7 +197,7 @@ class Snag {
"Failed to create a branch from the current state" "Failed to create a branch from the current state"
); );
git( git(
["add", "."], ["add", _config.project],
"Failed to prepare files for archiving" "Failed to prepare files for archiving"
); );
git( git(
@ -211,7 +211,7 @@ class Snag {
} else { } else {
// Если коммит является посленим в ветке // Если коммит является посленим в ветке
git( git(
["add", "."], ["add", _config.project],
"Failed to prepare files for archiving" "Failed to prepare files for archiving"
); );
git( git(
@ -250,7 +250,7 @@ class Snag {
[ [
"log", "log",
"--all", "--all",
"--date=format:%Y.%m.%d %H:%M", "--date=format:%Y.%m.%d %H:%M:%S",
"--pretty=" ~ format "--pretty=" ~ format
], ],
"Failed to retrieve the list of snapshots" "Failed to retrieve the list of snapshots"
@ -273,7 +273,7 @@ class Snag {
); );
if (result.output.length) { if (result.output.length) {
git( git(
["restore", "."], ["restore", _config.project],
"Failed to reset file changes state" "Failed to reset file changes state"
); );
git( git(
@ -381,8 +381,8 @@ class Snag {
// Выполнение git команд относительно распакованного архива // Выполнение git команд относительно распакованного архива
string[] customCommand = format( string[] customCommand = format(
"git --git-dir=%s --work-tree=%s", "git -C %s --git-dir=%s --work-tree=%s",
_config.git, tempDirectory tempDirectory, _config.git, tempDirectory
).split(); ).split();
// Необходимо проверить, что текущее состояние файлов не идентично файлам распакованного архива // Необходимо проверить, что текущее состояние файлов не идентично файлам распакованного архива
@ -406,7 +406,7 @@ class Snag {
); );
// Создание нового снимка на основе состояния файлов из распакованного архива // Создание нового снимка на основе состояния файлов из распакованного архива
result = execute(customCommand ~ ["add", "."]); result = execute(customCommand ~ ["add", tempDirectory]);
result.status && result.status &&
throw new SnagException( throw new SnagException(
"Failed to prepare files for archiving:\n" "Failed to prepare files for archiving:\n"
@ -427,7 +427,7 @@ class Snag {
// Сброс состояния файлов // Сброс состояния файлов
git( git(
["restore", "."], ["restore", _config.project],
"Failed to reset file changes state" "Failed to reset file changes state"
); );
git( git(

View file

@ -75,8 +75,8 @@ class SnagRules {
_gitignoreBak = _gitignore ~ ".bak"; _gitignoreBak = _gitignore ~ ".bak";
_baseCommand = format( _baseCommand = format(
"git --git-dir=%s --work-tree=%s", "git -C %s --git-dir=%s --work-tree=%s",
config.git, config.project config.project, config.git, config.project
).split(); ).split();
generate(); generate();

View file

@ -2,6 +2,8 @@ module snag.lib.lib;
import std.regex; import std.regex;
import std.process; import std.process;
import std.algorithm;
import std.string;
bool isValidHash(string hash) { bool isValidHash(string hash) {
auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$"; auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$";
@ -17,3 +19,9 @@ bool checkGit() {
auto result = execute(["which", "git"]); auto result = execute(["which", "git"]);
return !result.status; return !result.status;
} }
string[] splitByFirstSpace(string line) {
auto spaceIndex = line.indexOf(' ');
return spaceIndex == -1 ?
[line] : [line[0 .. spaceIndex], line[spaceIndex + 1..$]];
}

View file

@ -1,3 +1,3 @@
module snag.version_; module snag.version_;
enum snagVersion = "${PROJECT_VERSION_DISPLAY}"; enum snagVersion = "${PROJECT_VERSION_DISPLAY}${PROJECT_VERSION_SUFFIX}${GIT_VERSION_SUFFIX}";