Зачем? Немного предыстории
Всем привет! Работаю я в группе программистов – мы занимаемся программированием микроконтроллеров и блоков управления на их основе для наземного транспорта. Так уж у нас задалось, что версий одного и того же ПО с разным функционалом/багами довольно много, которое мы зашивали в разное время, то одна из задач: определить версию ПО или его библиотек в зашитом перед нами блоке.
Ранее, при сборке проекта использовались написанные нами шаблоны, из которых получался заголовочный файл с переменными, через которые можно было узнать версии ПО. При переходе на git столкнулись с такой проблемой, что похожих шаблонов не предусмотрено. Следовательно нужно делать самим!
Работаем!
Для начала пришлось определиться, что нам нужно от программы и какой будет формат работы с ней.
Сформировались вот такие вот требования:
- Программа должна запускаться и работать в 1 клик(для упрощения сборки проекта)
- В отдельных репозиториях должны быть файлы-шаблоны
- Рядом с программой будет файл конфигурационный файл, по которому будет собирать
- Созданные заголовочные файлы будут лежать рядом с шаблонами
И конечно же список заменяемых «переменных» для шаблона и сам шаблон:
- $git_commit — полный закомментированный текст команды «git status -s»
- $git_namespace — наименование заголовочного файла
- $git_countFromHead — число коммитов с создания репозитория
- $git_hash — хэш данного коммита(5 первых символов)
- $git_numUnrevisionedFiles — число незакоммиченных файлов
- $git_timeNow_second — Секунда сборки
- $git_timeNow_minute — Минута сборки
- $git_timeNow_hour — Час сборки
- $git_timeNow_day — День сборки
- $git_timeNow_month — Месяц сборки
- $git_timeNow_year — Год сборки
Почему такой странный формат времени? Потому что используем формат std::tm
Шаблон
$git_commit
#ifndef $git_namespace
#define $git_namespace
#include <ctime>
namespace $git_namespace
{
const unsigned int countFromHead = $git_countFromHead;
const unsigned int hash = 0x$git_hash;
const unsigned int numUnrevisionedFiles = $git_numUnrevisionedFiles;
const std::tm timeNow =
{
$git_timeNow_second,
$git_timeNow_minute,
$git_timeNow_hour,
$git_timeNow_day,
$git_timeNow_month,
$git_timeNow_year - 1900
};
}
#endif
Немного кода
Запускаем git и извлекаем данные
Process git = new Process();
git.StartInfo = new ProcessStartInfo(f[0], " --login -i");
git.StartInfo.RedirectStandardInput = true;// перенаправить вход
git.StartInfo.RedirectStandardOutput = true;//перенаправить выход
git.StartInfo.UseShellExecute = false;
git.Start();
git.StandardInput.WriteLine("git rev-list HEAD --count");
string revlist = git.StandardOutput.ReadLine();
Ищем и меняем файлы в шаблоне
string str = string.Empty;
File.Copy(path + filename + ".template",filename + ".h");
using (System.IO.StreamReader reader = System.IO.File.OpenText(filename + ".h"))
{
str = reader.ReadToEnd();
}
str = str.Replace("$git_namespace", cur_head[0]); // Хэш данного коммита
str = str.Replace("$git_countFromHead", git_revlist(cur_head));
str = str.Replace("$git_numUnrevisionedFiles", cur_commit.Length);
str = str.Replace("$git_hash", cur_hash); // Хэш данного коммита
str = str.Replace("$git_timeNow_second", DateTime.Now.Second.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_minute", DateTime.Now.Minute.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_hour", DateTime.Now.Hour.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_day", DateTime.Now.Day.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_month", DateTime.Now.Month.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_year", DateTime.Now.Year.ToString()); // Текущая время-дата
str = str.Replace("$git_commit", cur_commit); // состояние коммита
using (System.IO.StreamWriter file = new System.IO.StreamWriter(cur_head[0] + ".h"))
{
file.Write(str);
}
Листинг программы. Осторожно! Много быдлокода!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
namespace hgitcreate
{
class Program
{
static string git_hash(string[] head)
{
string git_hash = "0";
string[] f = Directory.GetFiles(@"C:\Program Files (x86)\Git\bin", "sh.exe"); //ищем git
if (f.Length == 0)
{
f = Directory.GetFiles(@"C:\Program Files\Git\bin", "sh.exe");
}
else
{
if (f.Length != 0)
{
Process git = new Process();
git.StartInfo = new ProcessStartInfo(f[0], " --login -i");//задаем имя исполняемого файла
//git.StartInfo.CreateNoWindow = true;//не создавать окно
//git.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
git.StartInfo.RedirectStandardInput = true;// перенаправить вход
git.StartInfo.RedirectStandardOutput = true;//перенаправить выход
git.StartInfo.UseShellExecute = false;//обязательный параметр, для работы предыдущих
// Process.Start(f[0], " --login -i");
git.Start();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardInput.WriteLine("git log");
git_hash = git.StandardOutput.ReadLine();
git_hash = git_hash.Substring(7, 7);
}
else
{
Console.Write("git(sh.exe) not found");
}
}
return git_hash;
}
static string git_commit(string[] head)
{
string git_commit = "0";
string[] f = Directory.GetFiles(@"C:\Program Files (x86)\Git\bin", "sh.exe"); //ищем git
if (f.Length == 0)
{
f = Directory.GetFiles(@"C:\Program Files\Git\bin", "sh.exe");
}
else
{
if (f.Length != 0)
{
Process git = new Process();
git.StartInfo = new ProcessStartInfo(f[0], " --login -i");//задаем имя исполняемого файла
//git.StartInfo.CreateNoWindow = true;//не создавать окно
//git.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
git.StartInfo.RedirectStandardInput = true;// перенаправить вход
git.StartInfo.RedirectStandardOutput = true;//перенаправить выход
git.StartInfo.UseShellExecute = false;//обязательный параметр, для работы предыдущих
// Process.Start(f[0], " --login -i");
git.Start();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardInput.WriteLine("git status -s");
git_commit = "/* ";
int i = 1;
git_commit += git.StandardOutput.ReadLine() + " \n ";
while (git.StandardOutput.Peek() != -1)
{
i++;
git_commit += git.StandardOutput.ReadLine() + " \n ";
}
git_commit += " */ \n //" + i.ToString();
}
else
{
Console.Write("git(sh.exe) not found");
}
}
return git_commit;
}
static string git_revlist(string[] head)
{
string git_revlist = "0";
string[] f = Directory.GetFiles(@"C:\Program Files (x86)\Git\bin", "sh.exe"); //ищем git
if (f.Length == 0)
{
f = Directory.GetFiles(@"C:\Program Files\Git\bin", "sh.exe");
}
else
{
if (f.Length != 0)
{
Process git = new Process();
git.StartInfo = new ProcessStartInfo(f[0], " --login -i");//задаем имя исполняемого файла
//git.StartInfo.CreateNoWindow = true;//не создавать окно
//git.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
git.StartInfo.RedirectStandardInput = true;// перенаправить вход
git.StartInfo.RedirectStandardOutput = true;//перенаправить выход
git.StartInfo.UseShellExecute = false;//обязательный параметр, для работы предыдущих
// Process.Start(f[0], " --login -i");
git.Start();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardOutput.ReadLine();
git.StandardInput.WriteLine("git rev-list HEAD --count");
git_revlist = git.StandardOutput.ReadLine();
}
else
{
Console.Write("git(sh.exe) not found");
}
}
return git_revlist;
}
static void Main(string[] args)
{
try
{
string[] heads = File.ReadAllLines("config.csv");
if (heads.Length > 0)
{
for (int i = 0; i < heads.Length; i++)
{
string[] cur_head = heads[i].Split(';');
File.Delete(cur_head[1] + cur_head[0] + ".h");
File.Copy(cur_head[1] + cur_head[0] + ".template", cur_head[1] + cur_head[0] + ".h");
string cur_hash = git_hash(cur_head);
string cur_commit = git_commit(cur_head);
//Console.ReadKey();
string str = string.Empty;
using (System.IO.StreamReader reader = System.IO.File.OpenText(cur_head[1] + cur_head[0] + ".h"))
{
str = reader.ReadToEnd();
}
str = str.Replace("$git_namespace", cur_head[0]); // Хэш данного коммита
str = str.Replace("$git_countFromHead", git_revlist(cur_head));
str = str.Replace("$git_numUnrevisionedFiles", cur_commit.Substring(cur_commit.Length - 1, 1));
str = str.Replace("$git_hash", cur_hash); // Хэш данного коммита
str = str.Replace("$git_timeNow_second", DateTime.Now.Second.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_minute", DateTime.Now.Minute.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_hour", DateTime.Now.Hour.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_day", DateTime.Now.Day.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_month", DateTime.Now.Month.ToString()); // Текущая время-дата
str = str.Replace("$git_timeNow_year", DateTime.Now.Year.ToString()); // Текущая время-дата
str = str.Replace("$git_commit", cur_commit); // состояние коммита
using (System.IO.StreamWriter file = new System.IO.StreamWriter(cur_head[1] + cur_head[0] + ".h"))
{
file.Write(str);
}
}
}
else
{
Console.WriteLine("Конфигурационный файл пусть");
}
}
catch(ArgumentException ex)
{
Console.WriteLine(ex.Message);
// Console.ReadKey();
}
}
}
}
Готовый заголовочный файл
/* D ../../../git_header_maker/git.ps1
D ../../../git_header_maker/gitAll.ps1
M ../../../git_header_maker/git_test1.h
M ../../../git_header_maker/git_test2.h
D "../../../git_header_maker/git_version_lpc2000 \342\200\224 \320\272\320\276\320\277\320\270\321\217.h"
M ../../../git_header_maker/git_version_lpc2000.h
D ../../../git_header_maker/git_version_lpc2000.h
M ../../App.config
M ../../Program.cs
M ../../Properties/AssemblyInfo.cs
M ../../hgitcreate.csproj
?? ../../../config.csv
?? ../../../hgitcreate.exe
?? ../../../main exe/
*/
//14
#ifndef git_version_lpc2000
#define git_version_lpc2000
#include <ctime>
namespace git_version_lpc2000
{
const unsigned int countFromHead = 3;
const unsigned int hash = 0x957d20e;
const unsigned int numUnrevisionedFiles = 4;
const std::tm timeNow =
{
56,
33,
17,
3,
7,
2015 - 1900
};
}
#endif
Выводы
А вывода нет, просто небольшой костыль для упрощения сборки проекта и кому-нибудь на заметку.
Rumlin
А почему не на хабре опубликовано?
Kubatai
И правда, приношу свои извинения, немного промахнулся с целевой аудиторией. Перепроверил несколько раз на предмет опечаток/ошибок, но в конце концов промахнулся с сайтом.