เราถูกบังคับให้คิดค้นวิธีแก้ปัญหาอื่นเนื่องจากเราต้องการเวลาในการปรับเปลี่ยนโดยเฉพาะและไม่ต้องใช้เวลาและโซลูชันนี้ยังต้องพกพาได้ด้วย (เช่นการทำให้ python ทำงานในการติดตั้งคอมไพล์ของ windows ไม่ใช่เรื่องง่าย) และรวดเร็ว มันคล้ายกับโซลูชันของ David Hardeman ซึ่งฉันตัดสินใจที่จะไม่ใช้เนื่องจากไม่มีเอกสารประกอบ (จากที่เก็บฉันไม่สามารถเข้าใจได้ว่ารหัสของเขาทำอะไรกันแน่)
โซลูชันนี้เก็บ mtimes ไว้ในไฟล์. mtimes ในที่เก็บ git อัปเดตตามการคอมมิต (jsut เลือก mtimes ของไฟล์ที่จัดฉาก) และนำไปใช้ในการชำระเงิน ทำงานได้แม้กับ git เวอร์ชัน cygwin / mingw (แต่คุณอาจต้องคัดลอกไฟล์บางไฟล์จาก cygwin มาตรฐานไปยังโฟลเดอร์ของ git)
โซลูชันประกอบด้วย 3 ไฟล์:
- mtimestore - สคริปต์หลักที่มี 3 ตัวเลือก -a (บันทึกทั้งหมด - สำหรับการเริ่มต้นใน repo ที่มีอยู่แล้ว (ทำงานกับไฟล์ที่มีประสบการณ์ด้าน git), -s (เพื่อบันทึกการเปลี่ยนแปลงแบบทีละขั้น) และ -r เพื่อเรียกคืน สิ่งนี้มีให้เลือก 2 เวอร์ชัน - bash one (แบบพกพา, ดี, อ่านง่าย / แก้ไข) และรุ่น c (ยุ่ง แต่เร็วเพราะ mingw bash ช้าอย่างน่ากลัวซึ่งทำให้ไม่สามารถใช้ bash solution ในโครงการใหญ่ ๆ ได้)
- เบ็ดก่อนกระทำ
- เบ็ดหลังการชำระเงิน
การกระทำล่วงหน้า:
#!/bin/bash
mtimestore -s
git add .mtimes
หลังการชำระเงิน
#!/bin/bash
mtimestore -r
mtimestore - ทุบตี:
#!/bin/bash
function usage
{
echo "Usage: mtimestore (-a|-s|-r)"
echo "Option Meaning"
echo " -a save-all - saves state of all files in a git repository"
echo " -s save - saves mtime of all staged files of git repository"
echo " -r restore - touches all files saved in .mtimes file"
exit 1
}
function echodate
{
echo "$(stat -c %Y "$1")|$1" >> .mtimes
}
IFS=$'\n'
while getopts ":sar" optname
do
case "$optname" in
"s")
echo "saving changes of staged files to file .mtimes"
if [ -f .mtimes ]
then
mv .mtimes .mtimes_tmp
pattern=".mtimes"
for str in $(git diff --name-only --staged)
do
pattern="$pattern\|$str"
done
cat .mtimes_tmp | grep -vh "|\($pattern\)\b" >> .mtimes
else
echo "warning: file .mtimes does not exist - creating new"
fi
for str in $(git diff --name-only --staged)
do
echodate "$str"
done
rm .mtimes_tmp 2> /dev/null
;;
"a")
echo "saving mtimes of all files to file .mtimes"
rm .mtimes 2> /dev/null
for str in $(git ls-files)
do
echodate "$str"
done
;;
"r")
echo "restorim dates from .mtimes"
if [ -f .mtimes ]
then
cat .mtimes | while read line
do
timestamp=$(date -d "1970-01-01 ${line%|*} sec GMT" +%Y%m%d%H%M.%S)
touch -t $timestamp "${line##*|}"
done
else
echo "warning: .mtimes not found"
fi
;;
":")
usage
;;
*)
usage
;;
esac
mtimestore - c ++
#include <time.h>
#include <utime.h>
#include <sys/stat.h>
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <ctime>
#include <map>
void changedate(int time, const char* filename)
{
try
{
struct utimbuf new_times;
struct stat foo;
stat(filename, &foo);
new_times.actime = foo.st_atime;
new_times.modtime = time;
utime(filename, &new_times);
}
catch(...)
{}
}
bool parsenum(int& num, char*& ptr)
{
num = 0;
if(!isdigit(*ptr))
return false;
while(isdigit(*ptr))
{
num = num*10 + (int)(*ptr) - 48;
ptr++;
}
return true;
}
//splits line into numeral and text part - return numeral into time and set ptr to the position where filename starts
bool parseline(const char* line, int& time, char*& ptr)
{
if(*line == '\n' || *line == '\r')
return false;
time = 0;
ptr = (char*)line;
if( parsenum(time, ptr))
{
ptr++;
return true;
}
else
return false;
}
//replace \r and \n (otherwise is interpretted as part of filename)
void trim(char* string)
{
char* ptr = string;
while(*ptr != '\0')
{
if(*ptr == '\n' || *ptr == '\r')
*ptr = '\0';
ptr++;
}
}
void help()
{
std::cout << "version: 1.4" << std::endl;
std::cout << "usage: mtimestore <switch>" << std::endl;
std::cout << "options:" << std::endl;
std::cout << " -a saves mtimes of all git-versed files into .mtimes file (meant to be done on intialization of mtime fixes)" << std::endl;
std::cout << " -s saves mtimes of modified staged files into .mtimes file(meant to be put into pre-commit hook)" << std::endl;
std::cout << " -r restores mtimes from .mtimes file (that is meant to be stored in repository server-side and to be called in post-checkout hook)" << std::endl;
std::cout << " -h show this help" << std::endl;
}
void load_file(const char* file, std::map<std::string,int>& mapa)
{
std::string line;
std::ifstream myfile (file, std::ifstream::in);
if(myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
int time;
char* ptr;
if( parseline(line.c_str(), time, ptr))
{
if(std::string(ptr) != std::string(".mtimes"))
mapa[std::string(ptr)] = time;
}
}
myfile.close();
}
}
void update(std::map<std::string, int>& mapa, bool all)
{
char path[2048];
FILE *fp;
if(all)
fp = popen("git ls-files", "r");
else
fp = popen("git diff --name-only --staged", "r");
while(fgets(path, 2048, fp) != NULL)
{
trim(path);
struct stat foo;
int err = stat(path, &foo);
if(std::string(path) != std::string(".mtimes"))
mapa[std::string(path)]=foo.st_mtime;
}
}
void write(const char * file, std::map<std::string, int>& mapa)
{
std::ofstream outputfile;
outputfile.open(".mtimes", std::ios::out);
for(std::map<std::string, int>::iterator itr = mapa.begin(); itr != mapa.end(); ++itr)
{
if(*(itr->first.c_str()) != '\0')
{
outputfile << itr->second << "|" << itr->first << std::endl;
}
}
outputfile.close();
}
int main(int argc, char *argv[])
{
if(argc >= 2 && argv[1][0] == '-')
{
switch(argv[1][1])
{
case 'r':
{
std::cout << "restoring modification dates" << std::endl;
std::string line;
std::ifstream myfile (".mtimes");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
int time, time2;
char* ptr;
parseline(line.c_str(), time, ptr);
changedate(time, ptr);
}
myfile.close();
}
}
break;
case 'a':
case 's':
{
std::cout << "saving modification times" << std::endl;
std::map<std::string, int> mapa;
load_file(".mtimes", mapa);
update(mapa, argv[1][1] == 'a');
write(".mtimes", mapa);
}
break;
default:
help();
return 0;
}
} else
{
help();
return 0;
}
return 0;
}
- โปรดทราบว่าสามารถวาง hooks ลงใน template-directory เพื่อจัดวางตำแหน่งได้โดยอัตโนมัติ
ดูข้อมูลเพิ่มเติมได้ที่นี่
https://github.com/kareltucek/git-mtime-extension ข้อมูล
บางส่วนที่ล้าสมัยอยู่ที่
http://www.ktweb.cz/blog/index.php?page=page&id=116
// แก้ไข - ปรับปรุงเวอร์ชัน c ++:
- ตอนนี้เวอร์ชัน c ++ รักษาการเรียงลำดับตามตัวอักษร -> ความขัดแย้งในการผสานน้อยลง
- กำจัดระบบที่น่าเกลียด () การโทร
- ลบ $ git update-index - รีเฟรช $ จาก post-checkout hook ทำให้เกิดปัญหาบางอย่างกับการเปลี่ยนกลับภายใต้คอมไพล์ของเต่าและดูเหมือนจะไม่สำคัญมากนัก
- สามารถดาวน์โหลดแพ็คเกจ windows ของเราได้ที่http://ktweb.cz/blog/download/git-mtimestore-1.4.rar
// แก้ไขดู github สำหรับเวอร์ชันล่าสุด