それが最も実用的だと思われるので、私自身のアイデアの実装を回答として投稿して受け入れるつもりです。
だからここに解決策があります:
- ビルドごとに、次のデータを含むビルド ファイルに 1 行追加します。
- すべてのマージで、両方のビルド ファイルからの行を保持します
- ビルド数は、ビルド ファイルの合計行数です。
ビルド ファイルの各行は一意である必要があります。日付と時刻は、それを非常にユニークなものにします。2 人のユーザーが同時に自分のブランチでビルドを発行することはほとんどありません。ただし、発生する可能性があります。したがって、乱数が生成され、その可能性を減らすために追加されます。
ただし、問題が 1 つあります。でシードsrand
するとtime(NULL)
、両方のビルドがおそらく同時に行われるため、生成される数もたまたま同じになる可能性があります。したがって、乱数ジェネレーターには、clock()
または のミリ秒部分などの別の数値をシードすることができますgettimeofday()
。ランダムに生成されなくても、乱数の代わりにそれらの数値自体を配置できます。
それでも 2 行が同じ結果になった場合は、ダチョウのアルゴリズムを適用します。
アップデート:
私はそれを実装し、すべてが正常に動作します。最後に、clock_gettime(CLOCK_MONOTONIC, ...)
この関数で得られたナノ秒を乱数として使用して印刷しました。私が使用しなかった理由はclock()
、プログラムが非常に短いため、実行速度が の解像度よりも低く、結果としてclock()
0 を取得し続けたからです。
アップデート:
これが私が書いた最終的なコードです (その一部は別の場所から盗用されています!)。-lrt
一部のプラットフォームでは必要になる場合があります。
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
struct timespec
{
long tv_sec;
long tv_nsec;
};
/* Note: I copy-pasted this from internet (https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows/5404467#5404467)
* I tweaked it to return nanoseconds instead of microseconds
* It is much more complete than just finding tv_nsec, but I'm keeping it for possible future use. */
LARGE_INTEGER getFILETIMEoffset(void)
{
SYSTEMTIME s;
FILETIME f;
LARGE_INTEGER t;
s.wYear = 1970;
s.wMonth = 1;
s.wDay = 1;
s.wHour = 0;
s.wMinute = 0;
s.wSecond = 0;
s.wMilliseconds = 0;
SystemTimeToFileTime(&s, &f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
return t;
}
int clock_gettime(int X, struct timespec *tv)
{
LARGE_INTEGER t;
FILETIME f;
double microseconds;
static LARGE_INTEGER offset;
static double frequencyToNanoseconds;
static int initialized = 0;
static BOOL usePerformanceCounter = 0;
if (!initialized)
{
LARGE_INTEGER performanceFrequency;
initialized = 1;
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
if (usePerformanceCounter)
{
QueryPerformanceCounter(&offset);
frequencyToNanoseconds = (double)performanceFrequency.QuadPart/1000000000.0;
}
else
{
offset = getFILETIMEoffset();
frequencyToNanoseconds = 0.010;
}
}
if (usePerformanceCounter)
QueryPerformanceCounter(&t);
else
{
GetSystemTimeAsFileTime(&f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
}
t.QuadPart -= offset.QuadPart;
microseconds = (double)t.QuadPart/frequencyToNanoseconds;
t.QuadPart = microseconds;
tv->tv_sec = t.QuadPart/1000000000;
tv->tv_nsec = t.QuadPart%1000000000;
return 0;
}
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 0 /* not used anyway */
#endif
#endif
int main(int argc, char **argv)
{
time_t now_sec;
struct tm *now;
FILE *bout;
struct timespec now_clk;
if (argc < 2)
{
printf("Usage: %s build_file_name\n\n", argv[0]);;
return EXIT_FAILURE;
}
bout = fopen(argv[1], "a");
if (!bout)
{
printf("Could not open file: %s\n\n", argv[1]);
return EXIT_FAILURE;
}
time(&now_sec);
now = gmtime(&now_sec);
fprintf(bout, "%02d/%02d/%04d %02d:%02d:%02d", now->tm_mday, now->tm_mon+1, now->tm_year+1900, now->tm_hour, now->tm_min, now->tm_sec);
clock_gettime(CLOCK_MONOTONIC, &now_clk);
fprintf(bout, " %ld\n", now_clk.tv_nsec);
return EXIT_SUCCESS;
}
うまくいけば、これは誰かに役立つでしょう。
アップデート
これを約9か月使用した後、これは非常に便利であると言えます. いくつかの観察事項は次のとおりです。
- Windows では、 の実装によって与えられる最後の要素
clock_gettime
は非常に小さく、同じ値を持つ回数の半分です。それにもかかわらず、それでももう少しランダムになります。
- Linux では、最後の要素はかなりランダムです。
- マージできるように、ビルド ファイル内の行をコミットするためだけに、時々「ビルド」コミットを実行する必要がありました。ただし、これは で回避できます
git stash
。
- これを使用すると、ほとんどの場合、マージ時に競合が発生しますが、それを解決するのは非常に簡単です (両方のファイルからの行が必要なため、差分マーカーを削除するだけです)。
wc -l
あなたの友達です。