Теоретические исследования
ОТЧЕТ
По лабораторной работе № 4
«Система контроля версий»
по дисциплине «Методы программирования»
Выполнили
студент гр. xxxxx/x И.И. Иванов
<подпись>
студент гр. xxxxx/x А.А. Александров
<подпись>
Проверил
В.Б. Вагисаров
<подпись>
Санкт-Петербург
Формулировка задания
Необходимо реализовать простой вариант системы контроля версий для текстовых файлов.
Программа с помощью меню реализует следующие команды:
Базовые:
- open <fname> <version> - открываем файл в версии <version>. Если версия не задана - открываем корневую версию (ее номер по умолчанию равен 0)
- print - отображает на экран текущую версию файла, с которым работаем.
Ф-ии редактирования:
- edit <i> <j> <data> - замена в текущей версии файла данных с индексом i (включительно) по индекс j (не включительно) на символы data
- add <i> <data> - добавление к текущей версии файла данных, начиная с позиции с индексом i
- remove <i> <j> - удаляем данные
Ф-ии работы с версиями:
- push - сохраняем текущую версию в виде разностного образа с предыдущей версией (не с корневой!). Функция возвращает номер версии, по которому можно впоследствии откатиться к этой версии.
- pull <№ версии> - делает текущей версию с переданным номером (т.е. перемещается по дереву версий, получая текущую версию из разностной информации на пути). Дальнейшее редактирование запоминается как изменения(разность) относительно этой (текущей) версией.
- delete_version <<№ версии> - удаляет версию из дерева. При этом корректируются наследники этой версии в дереве - разность теперь высчитывается относительно нового корня(предка удаленной вершины)
- rebase - перебалансирует дерево, помещая текущую версию в корень дерева путем перерассчета разностей версий относительно нового корня. Все номера версий остаются прежними, кроме 2х версий - текущей и бывшей корневой. Их номера меняются местами (т.е. текущая версия становится корнем дерева с номером 0, прежний корень забирает себе бывший номер этой версии)
теоретические исследования
Система управления версиями— программное обеспечение для облегчения работы с изменяющейся информацией. Система управления версиями позволяет хранить несколько версий одного и того же документа, при необходимости возвращаться к более ранним версиям, определять, кто и когда сделал то или иное изменение.
Система управления версиями обеспечивает хранение всех существовавших вариантов файлов и, как следствие, всех вариантов проекта в целом, имевших место с момента начала его разработки. Но само понятие «версии» в разных системах может трактоваться двумя различными способами.
Одни системы поддерживают версионность файлов. Это означает, что любой файл, появляющийся в проекте, получает собственный номер версии (обычно — номер 1, условной «нулевой» версией файла считается пустой файл с тем же именем). При каждой фиксации разработчиком изменений, затрагивающих файл, соответствующая часть фиксируемых изменений применяется к файлу и файл получает новый, обычно следующий по порядку, номер версии.
Для других систем понятие «версия» относится не к отдельному файлу, а к репозиторию целиком. Вновь созданный пустой репозиторий имеет версию 1 или 0, любая фиксация изменений приводит к увеличению этого номера (то есть даже при изменении одного файла на один байт весь репозиторий считается изменённым и получает новый номер версии).
Rebase — перенос точки ветвления (версии, от которой начинается ветвь) на более позднюю версию основной ветви. Например, после выпуска версии 1.0 проекта в стволе продолжается доработка (исправление ошибок, доработка имеющегося функционала), одновременно начинается работа над новой функциональностью в новой ветви. Через какое-то время в основной ветви происходит выпуск версии 1.1 (с исправлениями); теперь желательно, чтобы ветвь разработки новой функциональности включала изменения, произошедшие в стволе. Система самостоятельно определяет нужные наборы изменений и производит их слияние, после чего для ветви базовой версией становится версия 1.1; при последующем слиянии ветви со стволом система не рассматривает повторно изменения, внесённые между версиями 1.0 и 1.1, так как ветвь логически считается выделенной после версии 1.1.
Дельта-кодирование— способ представления данных в виде разницы (дельты) между последовательными данными вместо самих данных.Пожалуй, наиболее простой пример заключается в сохранении значений байтов как различия (дельты) между последовательными значениями, в отличие от самих значений. Поэтому вместо 2, 4, 6, 9, 7, мы будем сохранять 2, 2, 2, 3, −2.
Вариация дельта-кодирования, которая кодирует различия между префиксами или суффиксами строк, называется инкрементным кодированием. Оно в частности эффективно для отсортированных списков с малыми различиями между строками, такими, например, как список слов из словаря.
Результаты работы
Рис.1. – Главное меню и приветствие.
Рис.2. – команды открытия файлов и перехода к нужной версии.
Рис.3. – Открытие различных версий.
Рис.4. – Функция rebase, которая меняет текущую версию с корневой местами и пересчитывает дельта-файлы для всех версий на своём пути.
Рис.5. – Команды add и remove, которые добавляют и удаляют информацию.
Рис.6. – Команда push, которая сохраняет текущие изменения в новой версии путём подсчёта дельт, с предком.
ВЫВОды
Таким образом, в ходе выполнения лабораторной работы была разработана программа, представляющая собой простой вариант системы контроля версий для текстовых файлов. Реализованы базовые функции открытия и отображения текущей версии файла, функции редактирования (edit, add и remove), а также функции работы с версиями (push, pull, delete и rebase).
ПРИЛОЖЕНИЕ
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <locale>
#include <Windows.h>
#define M 100//Максимальная длина вводимой команды
void greeting(bool c)
{
if (c)
{
printf("Добро пожаловать в приложение, для работы с текстовыми файлами различных версий (расширение .txt) \n\n");
printf("Список доступных команд : \n");
printf("open \"<fname>\" <version> - открывает файл <fname> (без расширения) в версии <version>, если версия не указана, открывает файл с версией \"0\";\n");
printf("print - отображает на экран текущую версию файла, с которым работаем;\n");
printf("edit <i> <j> <data> - замена в текущей версии файла данных с индексом i (включительно) по индекс j (не включительно) на символы data;\n");
printf("add <i> <data> - добавление к текущей версии файла данных, начиная с позиции с индексом i;\n");
printf("push - сохраняет текущую версию в виде разностного образа с предыдущей версией;\n");
printf("pull <№ версии> - делает текущей версию с переданным номером;\n");
printf("delete_version <№ версии> - удаляет версию из дерева;\n");
printf("rebase - перебалансирует дерево, помещая текущую версию в корень дерева;\n");
printf("save \"<out-name>\" - сохраняет текущий вариант в указанный файл (без расширения);\n");
printf("remove <start_index> <end_index> - удаляет байты из текущей версии, начиная с индекса <start_index> включительно и заканчивая <end_index> не включительно.\n");
}
}
void delta_read(char(&buf)[100], char(&delta_str)[20])
{
char temp_str[100] = { '\0' };
strcpy_s(temp_str, buf);
if (delta_str[0] == '+')
{
int add_ind = 0, f = 2;
char ind[4] = { '\0' }, add_data[50] = { '\0' };
while ((int)delta_str[f] > 47 && (int)delta_str[f] < 58)
{
ind[strlen(ind)] = delta_str[f];
f++;
}
ind[strlen(ind)] = '\0';
add_ind = atoi(ind);
for (int ct = f + 1; ct < strlen(delta_str); ct++)
{
if (delta_str[ct] != '\n') add_data[strlen(add_data)] = delta_str[ct];
}
strncpy_s(temp_str, buf, add_ind);
temp_str[add_ind] = '\0';
strcat_s(temp_str, add_data);
int k = add_ind + strlen(add_data);
for (int ct = add_ind; ct < strlen(buf); ct++)
{
temp_str[k] = buf[ct];
k++;
}
temp_str[k] = '\0';
}
else if (delta_str[0] == '-')
{
int first_ind = 0, second_ind = 0, f = 2;
char ind_1[4] = { '\0' }, ind_2[4] = { '\0' };
while ((int)delta_str[f] > 47 && (int)delta_str[f] < 58)
{
ind_1[strlen(ind_1)] = delta_str[f];
f++;
}
ind_1[strlen(ind_1)] = '\0';
first_ind = atoi(ind_1);
f++;
while (f<strlen(delta_str) && delta_str[f] != '\n')
{
ind_2[strlen(ind_2)] = delta_str[f];
f++;
}
ind_2[strlen(ind_2)] = '\0';
second_ind = atoi(ind_2);
strncpy_s(temp_str, buf, first_ind);
int k = strlen(temp_str);
for (int ct = second_ind; ct < strlen(buf); ct++)
{
temp_str[k] = buf[ct];
k++;
}
temp_str[k] = '\0';
}
strcpy_s(buf, temp_str);
}
void numb_str(char(&numb)[4], int number)
{
int d = number / 10, e = number % 10;
if (d == 0)
{
char ce = e + 48;
numb[0] = ce;
numb[1] = '\0';
}
else
{
char ce = e + 48, cd = d + 48;
numb[0] = cd;
numb[1] = ce;
numb[2] = '\0';
}
}
bool correct_name(char(&str)[M], int &first_of_name, int &last_of_name)
{
int ct = 0, corr_symb = 0, ind_find = 0, have_name = 0;
char bad_symb[9] = { '/', '*', ':', '?', '"', '<', '>', '|', '\\' };
while (str[ind_find] != ' ') ind_find++;
for (int i = ind_find; i < strlen(str); i++)
if (str[i] == '"')
{
first_of_name = i + 1;
break;
}
for (int i = first_of_name; i < strlen(str); i++)
if (str[i] == '"')
{
last_of_name = i - 1;
break;
}
if (last_of_name != 0 && first_of_name != 0 && first_of_name <= last_of_name)
{
for (int i = 0; i < 9; i++)
for (int ii = first_of_name; ii < last_of_name + 1; ii++)
if (str[ii] == bad_symb[i])
{
corr_symb++;
break;
}
have_name++;
}
if (have_name == 0) printf("Отсутствует имя файла\n");
else if (corr_symb != 0) printf("Присутствуют некорректные символы /,*,\\,:,?,\",<,>,|\n");
else return(1);
return(0);
}
void new_vers(char(&newname)[M + 7], int ver_numb, char(&name)[M], bool mod)//создание имени версии
{
strcpy_s(newname, name);
if (ver_numb > 0)
{
char numb[4];
strcat_s(newname, "_");
numb_str(numb, ver_numb);
strcat_s(newname, numb);
}
if (mod == 0) strcat_s(newname, ".txt");
else strcat_s(newname, ".temp");
}
void get_vers(char(&buf_v)[100], int ver_numb, char(&name)[M])
{
FILE *forget = NULL;
char newname[M + 7] = { '\0' };
new_vers(newname, ver_numb, name, 0);
fopen_s(&forget, newname, "r");
char numb[4];
fgets(numb, 4, forget);
int old_numb = atoi(numb);
if (old_numb > 0)
{
get_vers(buf_v, old_numb, name);
}
char delta_str[20] = { '\0' };
while (fgets(delta_str, 20, forget) != NULL)
{
delta_read(buf_v, delta_str);
if (delta_str[0] != '-' && delta_str[0] != '+')
{
fclose(forget);
return;
}
}
fclose(forget);
}
bool open_f(char(&name)[M], char(&tempname)[M + 7], FILE **inf, int &n_vers, int &amount_of_vers, int last_of_name, char(&buf)[100], char(&str)[M])
{
FILE *foropen = NULL, *fvers = NULL, *ftemp = NULL;
char fversname[M + 7] = { '\0' };
char c;
int ct = 0;
int f = last_of_name + 2;
char version[5] = { '\0' };
while (str[f] == ' ') f++;
while ((int)str[f] > 47 && (int)str[f] < 58 && strlen(version)<4)
{
version[strlen(version)] = str[f];
f++;
}
n_vers = atoi(version);
if (n_vers == -1) n_vers = 0;
char newname[M + 7] = { '\0' };
new_vers(newname, n_vers, name, 0);
fopen_s(&foropen, newname, "r");
if (foropen == NULL)
{
n_vers = -1;
printf("Файл с этой версией не существует.\n");
return(0);
}
else
{
FILE *core = NULL;
fclose(foropen);
char corename[M + 7] = { '\0' };
strcpy_s(fversname, name);
strcat_s(fversname, "_vers.txt");
fopen_s(&fvers, fversname, "r");
if (fvers == NULL)
{
fopen_s(&fvers, fversname, "a");
amount_of_vers = 0;
}
else
{
char vers_numb[4] = { '\0' };
fgets(vers_numb, 4, fvers);
amount_of_vers = atoi(vers_numb);
}
fclose(fvers);
fvers = NULL;
amount_of_vers++;
new_vers(tempname, amount_of_vers, name, 1);
fopen_s(&ftemp, tempname, "w");
char numb[4];
numb_str(numb, n_vers);
fprintf(ftemp, numb);
fprintf(ftemp, "\n");
fclose(ftemp);
new_vers(corename, 0, name, 0);
fopen_s(&core, corename, "r");
while ((c = fgetc(core)) != EOF)
{
buf[ct] = c;
ct++;
}
buf[ct] = '\0';
if (n_vers > 0)
get_vers(buf, n_vers, name);
*inf = foropen;
fclose(core);
return(1);
}
fclose(foropen);
return(0);
}
bool pull_f(char(&core_name)[M], char(&tempname)[M + 7], FILE **inf, int &n_vers, int &amount_of_vers, char(&buf)[100], char(&str)[M])
{
remove(tempname);
char for_open[M] = "open \"";
n_vers = -1;
amount_of_vers = -1;
strcat_s(for_open, core_name);
for_open[6 + strlen(core_name)] = '\"';
for_open[7 + strlen(core_name)] = ' ';
int f = 4;
while (str[f] == ' ') f++;
int ct = 8 + strlen(core_name);
for (int i = f; i < strlen(str) + 1; i++)
{
for_open[ct] = str[i];
ct++;
}
*inf = NULL;
int last_of_name = 5 + strlen(core_name);
if (open_f(core_name, tempname, inf, n_vers, amount_of_vers, last_of_name, buf, for_open)) return(1);
else return(0);
}
bool remove_f(char(&core_name)[M], char(&tempname)[M + 7], int &n_vers, char(&buf)[100], char(&str)[M], int amount_of_vers)
{
FILE *ftemp = NULL;
int first_ind = 0, second_ind = 0, f = 6;
while (str[f] == ' ') f++;
char ind_1[4] = { '\0' }, ind_2[4] = { '\0' };
char temp_str[100] = { '\0' }, delta_str[100] = { '\0' };
while ((int)str[f] > 47 && (int)str[f] < 58)
{
ind_1[strlen(ind_1)] = str[f];
f++;
}
ind_1[strlen(ind_1)] = '\0';
first_ind = atoi(ind_1);
f++;
while ((int)str[f] > 47 && (int)str[f] < 58)
{
ind_2[strlen(ind_2)] = str[f];
f++;
}
ind_2[strlen(ind_2)] = '\0';
second_ind = atoi(ind_2);
if (strlen(ind_1) == 0 || strlen(ind_2) == 0)
{
printf("Неверные индексы.\n");
return(0);
}
if (second_ind <= strlen(buf) && first_ind > -1 && first_ind <= second_ind)
{
strncpy_s(temp_str, buf, first_ind);
int k = strlen(temp_str);
for (int ct = second_ind; ct < strlen(buf); ct++)
{
temp_str[k] = buf[ct];
k++;
}
temp_str[k] = '\0';
strcpy_s(buf, temp_str);
delta_str[0] = '-'; delta_str[1] = ' ';
strcat_s(delta_str, ind_1);
delta_str[2 + strlen(ind_1)] = ' ';
delta_str[3 + strlen(ind_1)] = '\0';
strcat_s(delta_str, ind_2);
fopen_s(&ftemp, tempname, "a");
fprintf(ftemp, delta_str);
fprintf(ftemp, "\n");
fclose(ftemp);
return(1);
}
else printf("Неверные индексы.\n");
return(0);
}
bool add_f(char(&core_name)[M], char(&tempname)[M + 7], int &n_vers, char(&buf)[100], char(&str)[M], int amount_of_vers)
{
FILE *ftemp = NULL;
int add_ind = 0, f = 3;
char temp_str[100] = { '\0' }, delta_str[100] = { '\0' };
char ind[4] = { '\0' }, add_data[50] = { '\0' };
while (str[f] == ' ') f++;
while ((int)str[f] > 47 && (int)str[f] < 58 && strlen(ind)<3)
{
ind[strlen(ind)] = str[f];
f++;
}
ind[strlen(ind)] = '\0';
add_ind = atoi(ind);
if (strlen(ind) == 0)
{
printf("Неверный индекс.\n");
return(0);
}
if (add_ind < strlen(buf) && add_ind>-1)
{
while (str[f] == ' ') f++;
for (int ct = f; ct < strlen(str); ct++)
{
if (str[ct] != '\n') add_data[strlen(add_data)] = str[ct];
}
strncpy_s(temp_str, buf, add_ind);
temp_str[add_ind] = '\0';
strcat_s(temp_str, add_data);
int k = add_ind + strlen(add_data);
for (int ct = add_ind; ct < strlen(buf); ct++)
{
temp_str[k] = buf[ct];
k++;
}
temp_str[k] = '\0';
strcpy_s(buf, temp_str);
delta_str[0] = '+'; delta_str[1] = ' ';
strcat_s(delta_str, ind);
delta_str[2 + strlen(ind)] = ' ';
delta_str[3 + strlen(ind)] = '\0';
strcat_s(delta_str, add_data);
fopen_s(&ftemp, tempname, "a");
fprintf(ftemp, delta_str);
fprintf(ftemp, "\n");
fclose(ftemp);
return(1);
}
else printf("Неверный индекс.\n");
return(0);
}
bool edit_f(char(&core_name)[M], char(&tempname)[M + 7], int &n_vers, char(&buf)[100], char(&str)[M], int amount_of_vers)
{
int f = 4;
while (str[f] == ' ') f++;
int first_ind = f;
while ((int)str[f] > 47 && (int)str[f] < 58) f++;
while (str[f] == ' ') f++;
int second_ind = f;
while ((int)str[f] > 47 && (int)str[f] < 58) f++;
while (str[f] == ' ') f++;
int data_ind = f;
int ct = 7;
char for_rem[100] = "remove ";
for (int i = first_ind; i < data_ind; i++)
{
for_rem[ct] = str[i];
ct++;
}
if (!remove_f(core_name, tempname, n_vers, buf, for_rem, amount_of_vers)) return(0);
ct = 4;
char for_add[100] = "add ";
for (int i = first_ind; i < second_ind; i++)
{
for_add[ct] = str[i];
ct++;
}
for (int i = data_ind; i < strlen(str); i++)
{
for_add[ct] = str[i];
ct++;
}
if (!add_f(core_name, tempname, n_vers, buf, for_add, amount_of_vers)) return(0);
return(1);
}
void push_f(char(&core_name)[M], char(&tempname)[M + 7], FILE **inf, int &n_vers, int &amount_of_vers, char(&buf)[100], char(&str)[M])
{
char new_version[M + 7] = { '\0' };
new_vers(new_version, amount_of_vers, core_name, 0);
CopyFile(tempname, new_version, false);
remove(tempname);
FILE *fvers = NULL;
char fversname[M + 7] = { '\0' };
strcpy_s(fversname, core_name);
strcat_s(fversname, "_vers.txt");
fopen_s(&fvers, fversname, "w");
char numb[4];
numb_str(numb, amount_of_vers);
fprintf(fvers, numb);
fclose(fvers);
*inf = NULL;
n_vers = -1;
printf("Номер версии: %i.\n", amount_of_vers);
amount_of_vers = -1;
}
bool delete_f(char(&core_name)[M], int amount_of_vers, char(&str)[M], int n_vers)
{
FILE *fdel = NULL;
int f = 15, del_vers = 0;
char ind[4] = { '\0' };
char del_name[M + 7] = { '\0' };
while (str[f] == ' ') f++;
while ((int)str[f] > 47 && (int)str[f] < 58)
{
ind[strlen(ind)] = str[f];
f++;
}
ind[strlen(ind)] = '\0';
del_vers = atoi(ind);
if (del_vers == n_vers)
{
printf("Невозможно удалить версию, когда она открыта.\n");
return(0);
}
if (strlen(ind) == 0)
{
printf("Неверный индекс.\n");
return(0);
}
new_vers(del_name, del_vers, core_name, 0);
fopen_s(&fdel, del_name, "r");
if (fdel == NULL)
{
printf("Файла с такой версией не существует.\n");
return(0);
}
int ct = 0;
for (int i = 1; i < amount_of_vers; i++)
{
char check_name[M + 7] = { '\0' };
char parent[4] = { '\0' };
int par = 0;
new_vers(check_name, i, core_name, 0);
FILE *fcheck = NULL, *ftemp = NULL;
fopen_s(&fcheck, check_name, "r");
if (fcheck != NULL)
{
fgets(parent, 4, fcheck);
par = atoi(parent);
if (par == del_vers)
{
char temp_name[M + 7] = { '\0' };
new_vers(temp_name, i, core_name, 1);
CopyFile(del_name, temp_name, false);
fopen_s(&ftemp, temp_name, "a");
char delta_str[20] = { '\0' };
while (fgets(delta_str, 20, fcheck) != NULL)
{
fprintf(ftemp, delta_str);
}
fclose(ftemp);
fclose(fcheck);
CopyFile(temp_name, check_name, false);
remove(temp_name);
continue;
}
}
fclose(fcheck);
fcheck = NULL;
}
fclose(fdel);
remove(del_name);
return(1);
}
void rebase_f(char(&core_name)[M], char(&tempname)[M + 7], int amount_of_vers, char(&str)[M], int &n_vers)
{
char buf[100];
char vers_line[20] = { '\0' };
int ct = 0;
while (n_vers >= 0)
{
FILE *ftemp = NULL, *fdelta = NULL;
char temp_name[M + 7] = { '\0' };
char delta_name[M + 7] = { '\0' };
new_vers(temp_name, n_vers, core_name, 1);
new_vers(delta_name, n_vers, core_name, 0);
fopen_s(&ftemp, temp_name, "w");
fopen_s(&fdelta, delta_name, "r");
if (ct == 0)
{
FILE *fakeinf = NULL;
char numb[4], fakestr[M] = "pull ";
char fake_tempname[M + 7];
numb_str(numb, n_vers);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
vers_line[ct] = n_vers;
ct++;
pull_f(core_name, fake_tempname, &fakeinf, fake1, fake2, buf, fakestr);
}
if (n_vers > 0)
{
char numb[4] = { '\0' };
fgets(numb, 4, fdelta);
int number = atoi(numb);
vers_line[ct] = (char)number;
ct++;
n_vers = number;
}
else
{
fprintf(ftemp, buf);
fgets(buf, M, fdelta);
n_vers = -1;
}
fclose(ftemp);
fclose(fdelta);
}
int i = 0;
while (ct - 2 * i - 2 > 0)
{
int first_delta = (int)vers_line[i];
int second_delta = (int)vers_line[ct - i - 2];
FILE *ftemp = NULL, *fdelta = NULL;
char temp_name[M + 7] = { '\0' };
char delta_name[M + 7] = { '\0' };
new_vers(temp_name, first_delta, core_name, 1);
new_vers(delta_name, second_delta, core_name, 0);
fopen_s(&ftemp, temp_name, "w");
fopen_s(&fdelta, delta_name, "r");
char delta[20] = { '\0' };
int first_parent = (int)vers_line[i + 1];
int second_parent = (int)vers_line[ct - i - 1];
fgets(delta, 20, fdelta);
char numb[4];
numb_str(numb, first_parent);
fprintf(ftemp, numb);
fprintf(ftemp, "\n");
int amount_of_str = 0;
rewind(fdelta);
while (fgets(delta, 20, fdelta) != NULL) amount_of_str++;
while (amount_of_str > 1)
{
rewind(fdelta);
FILE *fakeinf = NULL;
char fakestr[M] = "pull ";
char fake_tempname3[M + 7];
numb_str(numb, second_parent);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
pull_f(core_name, fake_tempname3, &fakeinf, fake1, fake2, buf, fakestr);
for (int str_i = 0; str_i < amount_of_str-1; str_i++)
{
fgets(delta, 20, fdelta);
delta_read(buf, delta);
}
fgets(delta, 20, fdelta);
char reversed_delta[20] = { '\0' };
if (delta[0] == '+')
{
reversed_delta[0] = '-';
reversed_delta[1] = ' ';
int add_ind = 0, f = 2;
char ind[4] = { '\0' }, add_data[50] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind[strlen(ind)] = delta[f];
reversed_delta[f] = delta[f];
f++;
}
ind[strlen(ind)] = '\0';
reversed_delta[f] = ' ';
add_ind = atoi(ind);
for (int count = f + 1; count < strlen(delta); count++)
{
if (delta[count] != '\n') add_data[strlen(add_data)] = delta[count];
}
add_ind += strlen(add_data);
numb_str(numb, add_ind);
strcat_s(reversed_delta, numb);
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
else if (delta[0] == '-')
{
reversed_delta[0] = '+';
reversed_delta[1] = ' ';
int first_ind = 0, second_ind = 0, f = 2;
char ind_1[4] = { '\0' }, ind_2[4] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind_1[strlen(ind_1)] = delta[f];
f++;
}
ind_1[strlen(ind_1)] = '\0';
first_ind = atoi(ind_1);
f++;
while (f < strlen(delta) && delta[f] != '\n')
{
ind_2[strlen(ind_2)] = delta[f];
f++;
}
ind_2[strlen(ind_2)] = '\0';
second_ind = atoi(ind_2);
numb_str(numb, first_ind);
strcat_s(reversed_delta, numb);
reversed_delta[2 + strlen(numb)] = ' ';
int scht = 3 + strlen(numb);
for (int w = first_ind; w < second_ind; w++)
{
reversed_delta[scht] = buf[w];
scht++;
}
reversed_delta[scht] = '\0';
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
amount_of_str--;
}
fclose(ftemp);
fclose(fdelta);
new_vers(temp_name, second_delta, core_name, 1);
new_vers(delta_name, first_delta, core_name, 0);
fopen_s(&ftemp, temp_name, "w");
fopen_s(&fdelta, delta_name, "r");
fgets(delta, 20, fdelta);
numb_str(numb, second_parent);
fprintf(ftemp, numb);
fprintf(ftemp, "\n");
amount_of_str = 0;
rewind(fdelta);
while (fgets(delta, 20, fdelta) != NULL) amount_of_str++;
while (amount_of_str > 1)
{
rewind(fdelta);
FILE *fakeinf = NULL;
char fakestr[M] = "pull ";
char fake_tempname3[M + 7];
numb_str(numb, second_parent);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
pull_f(core_name, fake_tempname3, &fakeinf, fake1, fake2, buf, fakestr);
for (int str_i = 0; str_i < amount_of_str - 1; str_i++)
{
fgets(delta, 20, fdelta);
delta_read(buf, delta);
}
fgets(delta, 20, fdelta);
char reversed_delta[20] = { '\0' };
if (delta[0] == '+')
{
reversed_delta[0] = '-';
reversed_delta[1] = ' ';
int add_ind = 0, f = 2;
char ind[4] = { '\0' }, add_data[50] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind[strlen(ind)] = delta[f];
reversed_delta[f] = delta[f];
f++;
}
ind[strlen(ind)] = '\0';
reversed_delta[f] = ' ';
add_ind = atoi(ind);
for (int count = f + 1; count < strlen(delta); count++)
{
if (delta[count] != '\n') add_data[strlen(add_data)] = delta[count];
}
add_ind += strlen(add_data);
numb_str(numb, add_ind);
strcat_s(reversed_delta, numb);
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
else if (delta[0] == '-')
{
FILE *fakeinf = NULL;
char fakestr[M] = "pull ";
char fake_tempname2[M + 7];
numb_str(numb, first_parent);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
pull_f(core_name, fake_tempname2, &fakeinf, fake1, fake2, buf, fakestr);
memset(fake_tempname2, 0, sizeof(fake_tempname2));
reversed_delta[0] = '+';
reversed_delta[1] = ' ';
int first_ind = 0, second_ind = 0, f = 2;
char ind_1[4] = { '\0' }, ind_2[4] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind_1[strlen(ind_1)] = delta[f];
f++;
}
ind_1[strlen(ind_1)] = '\0';
first_ind = atoi(ind_1);
f++;
while (f < strlen(delta) && delta[f] != '\n')
{
ind_2[strlen(ind_2)] = delta[f];
f++;
}
ind_2[strlen(ind_2)] = '\0';
second_ind = atoi(ind_2);
numb_str(numb, first_ind);
strcat_s(reversed_delta, numb);
reversed_delta[2 + strlen(numb)] = ' ';
int scht = 3 + strlen(numb);
for (int w = first_ind; w < second_ind; w++)
{
reversed_delta[scht] = buf[w];
scht++;
}
reversed_delta[scht] = '\0';
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
amount_of_str--;
}
fclose(ftemp);
fclose(fdelta);
i++;
}
if ((ct - i * 2 - 2) == 0)
{
FILE *ftemp = NULL, *fdelta = NULL;
char temp_name[M + 7] = { '\0' };
char delta_name[M + 7] = { '\0' };
int first_parent = (int)vers_line[i + 1];
int first_delta = (int)vers_line[i];
new_vers(temp_name, first_delta, core_name, 1);
new_vers(delta_name, first_delta, core_name, 0);
fopen_s(&ftemp, temp_name, "w");
fopen_s(&fdelta, delta_name, "r");
char delta[20] = { '\0' }, numb[4];
numb_str(numb, first_parent);
fprintf(ftemp, numb);
fprintf(ftemp, "\n");
int amount_of_str = 0;
rewind(fdelta);
while (fgets(delta, 20, fdelta) != NULL) amount_of_str++;
while (amount_of_str > 1)
{
rewind(fdelta);
FILE *fakeinf = NULL;
char fakestr[M] = "pull ";
char fake_tempname3[M + 7];
numb_str(numb, first_parent);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
pull_f(core_name, fake_tempname3, &fakeinf, fake1, fake2, buf, fakestr);
for (int str_i = 0; str_i < amount_of_str - 1; str_i++)
{
fgets(delta, 20, fdelta);
delta_read(buf, delta);
}
fgets(delta, 20, fdelta);
char reversed_delta[20] = { '\0' };
if (delta[0] == '+')
{
reversed_delta[0] = '-';
reversed_delta[1] = ' ';
int add_ind = 0, f = 2;
char ind[4] = { '\0' }, add_data[50] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind[strlen(ind)] = delta[f];
reversed_delta[f] = delta[f];
f++;
}
ind[strlen(ind)] = '\0';
reversed_delta[f] = ' ';
add_ind = atoi(ind);
for (int count = f + 1; count < strlen(delta); count++)
{
if (delta[count] != '\n') add_data[strlen(add_data)] = delta[count];
}
add_ind += strlen(add_data);
numb_str(numb, add_ind);
strcat_s(reversed_delta, numb);
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
else if (delta[0] == '-')
{
FILE *fakeinf = NULL;
char fakestr[M] = "pull ";
char fake_tempname1[M + 7];
numb_str(numb, first_parent);
strcat_s(fakestr, numb);
int fake1 = 0, fake2 = 0;
pull_f(core_name, fake_tempname1, &fakeinf, fake1, fake2, buf, fakestr);
memset(fake_tempname1, 0, sizeof(fake_tempname1));
reversed_delta[0] = '+';
reversed_delta[1] = ' ';
int first_ind = 0, second_ind = 0, f = 2;
char ind_1[4] = { '\0' }, ind_2[4] = { '\0' };
while ((int)delta[f] > 47 && (int)delta[f] < 58)
{
ind_1[strlen(ind_1)] = delta[f];
f++;
}
ind_1[strlen(ind_1)] = '\0';
first_ind = atoi(ind_1);
f++;
while (f < strlen(delta) && delta[f] != '\n')
{
ind_2[strlen(ind_2)] = delta[f];
f++;
}
ind_2[strlen(ind_2)] = '\0';
second_ind = atoi(ind_2);
numb_str(numb, first_ind);
strcat_s(reversed_delta, numb);
reversed_delta[2 + strlen(numb)] = ' ';
int scht = 3 + strlen(numb);
for (int w = first_ind; w < second_ind; w++)
{
reversed_delta[scht] = buf[w];
scht++;
}
reversed_delta[scht] = '\0';
fprintf(ftemp, reversed_delta);
fprintf(ftemp, "\n");
}
amount_of_str--;
}
fclose(ftemp);
fclose(fdelta);
}
char temp_exch[M + 7], data_exch[M + 7];
new_vers(data_exch, 0, core_name, 0);
new_vers(temp_exch, 0, core_name, 1);
remove(data_exch);
CopyFile(temp_exch, data_exch, false);
remove(temp_exch);
int len = strlen(vers_line);
int j=0;
while (len - 2 * j > 1)
{
int for_temp_exch = (int)vers_line[j];
int for_data_exch = (int)vers_line[j];
char name_temp_exch[M + 7], name_data_exch[M + 7];
new_vers(name_data_exch, for_data_exch, core_name, 0);
new_vers(name_temp_exch, for_temp_exch, core_name, 1);
remove(name_data_exch);
CopyFile(name_temp_exch, name_data_exch, false);
remove(name_temp_exch);
for_temp_exch = (int)vers_line[len - j - 1];
for_data_exch = (int)vers_line[len - j - 1];
new_vers(name_data_exch, for_data_exch, core_name, 0);
new_vers(name_temp_exch, for_temp_exch, core_name, 1);
remove(name_data_exch);
CopyFile(name_temp_exch, name_data_exch, false);
remove(name_temp_exch);
j++;
}
if (len - 2 * j == 1)
{
int for_temp_exch = (int)vers_line[j];
int for_data_exch = (int)vers_line[len - j];
char name_temp_exch[M + 7], name_data_exch[M + 7];
new_vers(name_data_exch, for_data_exch, core_name, 0);
new_vers(name_temp_exch, for_temp_exch, core_name, 1);
remove(name_data_exch);
CopyFile(name_temp_exch, name_data_exch, false);
remove(name_temp_exch);
}
}
void main(void)
{
char tempname[M + 7] = { '\0' };
char core_name[M] = { '\0' };//Имя файла
char buf[100] = { '\0' };
FILE *inf = NULL;
int n_vers = -1, amount_of_vers = -1;
setlocale(LC_ALL, "Russian");
greeting(1);
char add[] = "add ",
ed[] = "edit ",
del[] = "delete_version ",
op[] = "open ",
ph[] = "push",
pl[] = "pull ",
rb[] = "rebase",
pr[] = "print",
sv[] = "save ",
rem[] = "remove ",
txt[] = ".txt";
while (1)
{
printf("\nВведите команду... \n");
char str[M];
gets_s(str);
if (strncmp(str, add, 4) != 0
&& strncmp(str, ed, 5) != 0
&& strncmp(str, del, 15) != 0
&& strncmp(str, pl, 5) != 0
&& strncmp(str, op, 5) != 0
&& strcmp(str, rb) != 0
&& strcmp(str, ph) != 0
&& strcmp(str, pr) != 0
&& strncmp(str, sv, 5) != 0
&& strncmp(str, rem, 7) != 0) printf("Недопустимая команда. Повторите ввод.\n");
else
{
if ((strncmp(str, op, 5) != 0) && inf == NULL) printf("Необходимо открыть файл для работы команды.\n");
else
{
if (strncmp(str, sv, 5) == 0 || strncmp(str, op, 5) == 0)
{
int first_of_name = 0, last_of_name = 0;
if (correct_name(str, first_of_name, last_of_name))
{
char name[M] = { '\0' };//Имя файла
for (int i = first_of_name; i < last_of_name + 1; i++)
name[strlen(name)] = str[i];
name[strlen(name)] = '\0';
if (strncmp(str, op, 5) == 0)
{
if (open_f(name, tempname, &inf, n_vers, amount_of_vers, last_of_name, buf, str))
{
printf("Файл ");
printf(name);
printf(" версии ");
printf("%i", n_vers);
printf(" открыт.\n");
strcpy_s(core_name, name);
}
}
else if (strncmp(str, sv, 5) == 0)
{
strcat_s(name, ".txt");
FILE *forsave = NULL;
fopen_s(&forsave, name, "w");
fprintf(forsave, buf);
fclose(forsave);
printf("Текущая версия сохранена в файл ");
printf(name);
printf(".\n");
}
}
}
else
{
if (strcmp(str, pr) == 0)
{
printf("Содержимое текущей версии: \n");
printf(buf);
printf("\n");
}
else if (strncmp(str, add, 4) == 0)
{
if (add_f(core_name, tempname, n_vers, buf, str, amount_of_vers)) printf("Информация добавлена.\n");
}
else if (strncmp(str, rem, 7) == 0)
{
if (remove_f(core_name, tempname, n_vers, buf, str, amount_of_vers)) printf("Информация удалена.\n");
}
else if (strncmp(str, ed, 5) == 0)
{
if (edit_f(core_name, tempname, n_vers, buf, str, amount_of_vers)) printf("Информация изменена.\n");
}
else if (strncmp(str, pl, 5) == 0)
{
if (pull_f(core_name, tempname, &inf, n_vers, amount_of_vers, buf, str)) printf("Версия открыта.\n");
}
else if (strcmp(str, ph) == 0)
{
push_f(core_name, tempname, &inf, n_vers, amount_of_vers, buf, str);
printf("Файл версии сохранён.\n");
}
else if (strncmp(str, del, 15) == 0)
{
if (delete_f(core_name, amount_of_vers, str, n_vers)) printf("Файл успешно удалён.\n");
}
else if (strcmp(str, rb) == 0)
{
rebase_f(core_name, tempname, amount_of_vers, str, n_vers);
printf("Перебалансировано.\n");
}
}
}
}
}
}