mirror of
https://github.com/nestriness/cdc-file-transfer.git
synced 2026-01-30 10:35:37 +02:00
Merge pull request #80 from PatriosTheGreat/main
[cdc_rsync] [cdc_rsync_server] Add build ID
This commit is contained in:
@@ -159,6 +159,7 @@
|
|||||||
<ClCompile Include="$(MSBuildThisFileDirectory)metrics\metrics.cc" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)metrics\metrics.cc" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)cdc_stream\stop_service_command.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)cdc_stream\stop_service_command.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)common\ansi_filter.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)common\ansi_filter.h" />
|
||||||
|
<ClInclude Include="$(MSBuildThisFileDirectory)common\build_version.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)common\port_range_parser.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)common\port_range_parser.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)fastcdc\fastcdc.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)fastcdc\fastcdc.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)manifest\pending_assets_queue.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)manifest\pending_assets_queue.h" />
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ cc_library(
|
|||||||
hdrs = ["params.h"],
|
hdrs = ["params.h"],
|
||||||
deps = [
|
deps = [
|
||||||
":cdc_rsync_client",
|
":cdc_rsync_client",
|
||||||
|
"//common:build_version",
|
||||||
"//common:port_range_parser",
|
"//common:port_range_parser",
|
||||||
"@com_github_zstd//:zstd",
|
"@com_github_zstd//:zstd",
|
||||||
"@com_google_absl//absl/status",
|
"@com_google_absl//absl/status",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
|
#include "common/build_version.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/port_range_parser.h"
|
#include "common/port_range_parser.h"
|
||||||
#include "common/remote_util.h"
|
#include "common/remote_util.h"
|
||||||
@@ -38,8 +39,7 @@ void PrintError(const absl::FormatSpec<Args...>& format, Args... args) {
|
|||||||
enum class OptionResult { kConsumedKey, kConsumedKeyValue, kError };
|
enum class OptionResult { kConsumedKey, kConsumedKeyValue, kError };
|
||||||
|
|
||||||
const char kHelpText[] =
|
const char kHelpText[] =
|
||||||
R"(Synchronize files and directories
|
R"(
|
||||||
|
|
||||||
Matching files are skipped based on file size and modified time. For partially
|
Matching files are skipped based on file size and modified time. For partially
|
||||||
matching files only the differences are transferred. The destination directory
|
matching files only the differences are transferred. The destination directory
|
||||||
can be the same Windows machine or a remote Windows or Linux device.
|
can be the same Windows machine or a remote Windows or Linux device.
|
||||||
@@ -323,6 +323,8 @@ OptionResult HandleParameter(const std::string& key, const char* value,
|
|||||||
|
|
||||||
bool ValidateParameters(const Parameters& params, bool help) {
|
bool ValidateParameters(const Parameters& params, bool help) {
|
||||||
if (help) {
|
if (help) {
|
||||||
|
std::cout << "cdc_rsync - Synchronize files and directories. Version: "
|
||||||
|
<< BUILD_VERSION << "\n";
|
||||||
std::cout << kHelpText;
|
std::cout << kHelpText;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ cc_binary(
|
|||||||
"//cdc_rsync/base:cdc_interface",
|
"//cdc_rsync/base:cdc_interface",
|
||||||
"//cdc_rsync/base:message_pump",
|
"//cdc_rsync/base:message_pump",
|
||||||
"//cdc_rsync/base:server_exit_code",
|
"//cdc_rsync/base:server_exit_code",
|
||||||
|
"//common:build_version",
|
||||||
"//common:clock",
|
"//common:clock",
|
||||||
"//common:gamelet_component",
|
"//common:gamelet_component",
|
||||||
"//common:log",
|
"//common:log",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "cdc_rsync/base/server_exit_code.h"
|
#include "cdc_rsync/base/server_exit_code.h"
|
||||||
#include "cdc_rsync_server/cdc_rsync_server.h"
|
#include "cdc_rsync_server/cdc_rsync_server.h"
|
||||||
|
#include "common/build_version.h"
|
||||||
#include "common/gamelet_component.h"
|
#include "common/gamelet_component.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/status.h"
|
#include "common/status.h"
|
||||||
@@ -60,10 +61,16 @@ ServerExitCode GetExitCode(const absl::Status& status) {
|
|||||||
} // namespace cdc_ft
|
} // namespace cdc_ft
|
||||||
|
|
||||||
int main(int argc, const char** argv) {
|
int main(int argc, const char** argv) {
|
||||||
if (argc < 2) {
|
if (argc < 5) {
|
||||||
printf("Usage: cdc_rsync_server <port> cdc_rsync_server <size> <time> \n");
|
printf("cdc_rsync_server - Remote component of cdc_rsync. Version: %s\n\n",
|
||||||
printf(" where <size> and <time> are the file size and modified\n");
|
BUILD_VERSION);
|
||||||
printf(" timestamp (Unix epoch) of the corresponding component.\n");
|
printf(
|
||||||
|
"Usage: cdc_rsync_server <port> <build_version> cdc_rsync_server "
|
||||||
|
"<size> <time> \n");
|
||||||
|
printf(" where <size> is the file size, <time> is the modified\n");
|
||||||
|
printf(
|
||||||
|
" timestamp (Unix epoch) and <build_version> is the build "
|
||||||
|
"version of the server.\n");
|
||||||
return cdc_ft::kServerExitCodeGenericStartup;
|
return cdc_ft::kServerExitCodeGenericStartup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +89,7 @@ int main(int argc, const char** argv) {
|
|||||||
cdc_ft::Log::Initialize(
|
cdc_ft::Log::Initialize(
|
||||||
std::make_unique<cdc_ft::ConsoleLog>(cdc_ft::LogLevel::kWarning));
|
std::make_unique<cdc_ft::ConsoleLog>(cdc_ft::LogLevel::kWarning));
|
||||||
cdc_ft::CdcRsyncServer server;
|
cdc_ft::CdcRsyncServer server;
|
||||||
|
|
||||||
if (!server.CheckComponents(components)) {
|
if (!server.CheckComponents(components)) {
|
||||||
return cdc_ft::kServerExitCodeOutOfDate;
|
return cdc_ft::kServerExitCodeOutOfDate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ cc_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "build_version",
|
||||||
|
hdrs = ["build_version.h"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "dir_iter",
|
name = "dir_iter",
|
||||||
srcs = ["dir_iter.cc"],
|
srcs = ["dir_iter.cc"],
|
||||||
@@ -396,6 +401,7 @@ cc_library(
|
|||||||
":path",
|
":path",
|
||||||
":platform",
|
":platform",
|
||||||
":status",
|
":status",
|
||||||
|
"//common:build_version",
|
||||||
"@com_google_absl//absl/status",
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
],
|
],
|
||||||
|
|||||||
10
common/build_version.h
Normal file
10
common/build_version.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef BUILD_VERSION
|
||||||
|
#define DEV_BUILD_VERSION "DEV"
|
||||||
|
#ifdef CDC_BUILD_VERSION
|
||||||
|
#define TO_STR(arg) #arg
|
||||||
|
#define TO_STR_VALUE(arg) TO_STR(arg)
|
||||||
|
#define BUILD_VERSION TO_STR_VALUE(CDC_BUILD_VERSION)
|
||||||
|
#else
|
||||||
|
#define BUILD_VERSION DEV_BUILD_VERSION
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -18,20 +18,36 @@
|
|||||||
|
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
|
#include "common/build_version.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/status.h"
|
#include "common/status.h"
|
||||||
|
|
||||||
namespace cdc_ft {
|
namespace cdc_ft {
|
||||||
|
|
||||||
GameletComponent::GameletComponent(std::string filename, uint64_t size,
|
GameletComponent::GameletComponent(std::string build_version,
|
||||||
|
std::string filename, uint64_t size,
|
||||||
time_t modified_time)
|
time_t modified_time)
|
||||||
: filename(filename), size(size), modified_time(modified_time) {}
|
: build_version(build_version),
|
||||||
|
filename(filename),
|
||||||
|
size(size),
|
||||||
|
modified_time(modified_time) {}
|
||||||
|
|
||||||
GameletComponent::~GameletComponent() = default;
|
GameletComponent::~GameletComponent() = default;
|
||||||
|
|
||||||
bool GameletComponent::operator==(const GameletComponent& other) const {
|
bool GameletComponent::operator==(const GameletComponent& other) const {
|
||||||
return filename == other.filename && size == other.size &&
|
if (filename != other.filename) {
|
||||||
modified_time == other.modified_time;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If either build version is the dev version, it means that the component was
|
||||||
|
// built locally, so that we can't compare build versions. Fall back to
|
||||||
|
// comparing file_size and modified_time.
|
||||||
|
if (build_version != DEV_BUILD_VERSION &&
|
||||||
|
build_version != DEV_BUILD_VERSION) {
|
||||||
|
return build_version == other.build_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size == other.size && modified_time == other.modified_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameletComponent::operator!=(const GameletComponent& other) const {
|
bool GameletComponent::operator!=(const GameletComponent& other) const {
|
||||||
@@ -49,7 +65,7 @@ absl::Status GameletComponent::Get(
|
|||||||
absl::Status status = path::GetStats(path, &stats);
|
absl::Status status = path::GetStats(path, &stats);
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
return WrapStatus(status, "GetStats() failed for '%s'", path);
|
return WrapStatus(status, "GetStats() failed for '%s'", path);
|
||||||
components->emplace_back(path::BaseName(path), stats.size,
|
components->emplace_back(BUILD_VERSION, path::BaseName(path), stats.size,
|
||||||
stats.modified_time);
|
stats.modified_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,9 +77,9 @@ std::string GameletComponent::ToCommandLineArgs(
|
|||||||
const std::vector<GameletComponent>& components) {
|
const std::vector<GameletComponent>& components) {
|
||||||
std::string args;
|
std::string args;
|
||||||
for (const GameletComponent& comp : components) {
|
for (const GameletComponent& comp : components) {
|
||||||
args +=
|
args += absl::StrFormat("%s%s %s %u %d", args.empty() ? "" : " ",
|
||||||
absl::StrFormat("%s%s %u %d", args.empty() ? "" : " ",
|
comp.build_version.c_str(), comp.filename.c_str(),
|
||||||
comp.filename.c_str(), comp.size, comp.modified_time);
|
comp.size, comp.modified_time);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
@@ -72,9 +88,9 @@ std::string GameletComponent::ToCommandLineArgs(
|
|||||||
std::vector<GameletComponent> GameletComponent::FromCommandLineArgs(
|
std::vector<GameletComponent> GameletComponent::FromCommandLineArgs(
|
||||||
int argc, const char** argv) {
|
int argc, const char** argv) {
|
||||||
std::vector<GameletComponent> components;
|
std::vector<GameletComponent> components;
|
||||||
for (int n = 0; n + 2 < argc; n += 3) {
|
for (int n = 0; n + 3 < argc; n += 4) {
|
||||||
components.emplace_back(argv[n], std::stol(argv[n + 1]),
|
components.emplace_back(argv[n], argv[n + 1], std::stol(argv[n + 2]),
|
||||||
std::stol(argv[n + 2]));
|
std::stol(argv[n + 3]));
|
||||||
}
|
}
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,13 @@ namespace cdc_ft {
|
|||||||
// The components are considered fresh if both the timestamp and the file size
|
// The components are considered fresh if both the timestamp and the file size
|
||||||
// match.
|
// match.
|
||||||
struct GameletComponent {
|
struct GameletComponent {
|
||||||
|
std::string build_version;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
int64_t modified_time;
|
int64_t modified_time;
|
||||||
|
|
||||||
GameletComponent(std::string filename, uint64_t size, time_t modified_time);
|
GameletComponent(std::string build_version, std::string filename,
|
||||||
|
uint64_t size, time_t modified_time);
|
||||||
~GameletComponent();
|
~GameletComponent();
|
||||||
|
|
||||||
bool operator==(const GameletComponent& other) const;
|
bool operator==(const GameletComponent& other) const;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "common/gamelet_component.h"
|
#include "common/gamelet_component.h"
|
||||||
|
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
|
#include "common/build_version.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/status_test_macros.h"
|
#include "common/status_test_macros.h"
|
||||||
@@ -43,14 +44,14 @@ class GameletComponentTest : public ::testing::Test {
|
|||||||
path::Join(base_dir_, "other", "cdc_rsync_server");
|
path::Join(base_dir_, "other", "cdc_rsync_server");
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(GameletComponentTest, EqualityOperators) {
|
TEST_F(GameletComponentTest, EqualityOperators_DevelopmentVersion) {
|
||||||
constexpr uint64_t size1 = 1001;
|
constexpr uint64_t size1 = 1001;
|
||||||
constexpr uint64_t size2 = 1002;
|
constexpr uint64_t size2 = 1002;
|
||||||
|
|
||||||
constexpr int64_t modified_time1 = 5001;
|
constexpr int64_t modified_time1 = 5001;
|
||||||
constexpr int64_t modified_time2 = 5002;
|
constexpr int64_t modified_time2 = 5002;
|
||||||
|
|
||||||
GameletComponent a("file1", size1, modified_time1);
|
GameletComponent a(DEV_BUILD_VERSION, "file1", size1, modified_time1);
|
||||||
|
|
||||||
GameletComponent b = a;
|
GameletComponent b = a;
|
||||||
EXPECT_TRUE(a == b && !(a != b));
|
EXPECT_TRUE(a == b && !(a != b));
|
||||||
@@ -65,6 +66,38 @@ TEST_F(GameletComponentTest, EqualityOperators) {
|
|||||||
b = a;
|
b = a;
|
||||||
b.modified_time = modified_time2;
|
b.modified_time = modified_time2;
|
||||||
EXPECT_TRUE(!(a == b) && a != b);
|
EXPECT_TRUE(!(a == b) && a != b);
|
||||||
|
|
||||||
|
b = a;
|
||||||
|
b.size = size2;
|
||||||
|
b.build_version = "Specified";
|
||||||
|
EXPECT_TRUE(!(a == b) && a != b);
|
||||||
|
|
||||||
|
a.build_version = "Specified";
|
||||||
|
EXPECT_TRUE(a == b && !(a != b));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(GameletComponentTest, EqualityOperators_SpecifiedVersion) {
|
||||||
|
constexpr uint64_t size1 = 1001;
|
||||||
|
constexpr uint64_t size2 = 1002;
|
||||||
|
|
||||||
|
constexpr int64_t modified_time1 = 5001;
|
||||||
|
constexpr int64_t modified_time2 = 5002;
|
||||||
|
|
||||||
|
GameletComponent a("Specified", "file1", size1, modified_time1);
|
||||||
|
|
||||||
|
GameletComponent b = a;
|
||||||
|
EXPECT_TRUE(a == b && !(a != b));
|
||||||
|
|
||||||
|
b.filename = "file2";
|
||||||
|
EXPECT_TRUE(!(a == b) && a != b);
|
||||||
|
|
||||||
|
b = a;
|
||||||
|
b.size = size2;
|
||||||
|
EXPECT_TRUE(a == b && !(a != b));
|
||||||
|
|
||||||
|
b = a;
|
||||||
|
b.modified_time = modified_time2;
|
||||||
|
EXPECT_TRUE(a == b && !(a != b));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GameletComponentTest, GetValidComponents) {
|
TEST_F(GameletComponentTest, GetValidComponents) {
|
||||||
|
|||||||
Reference in New Issue
Block a user