From baf30b7b83822b7d6efd0c16761b8e42a1e96101 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Thu, 24 Dec 2015 00:11:06 +0100 Subject: Match namespace and directory structure --- src/tracking/change_tracker.cc | 92 ++++++++++++++++++++++++++++++++++++++++++ src/tracking/change_tracker.h | 32 +++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/tracking/change_tracker.cc create mode 100644 src/tracking/change_tracker.h (limited to 'src/tracking') diff --git a/src/tracking/change_tracker.cc b/src/tracking/change_tracker.cc new file mode 100644 index 0000000..913604e --- /dev/null +++ b/src/tracking/change_tracker.cc @@ -0,0 +1,92 @@ +#include "change_tracker.h" + +#include +#include + +namespace { + +// constants for increasing pair access readability +constexpr unsigned int EMPLACE_SUCCESS = 1; +constexpr unsigned int FILE_NAME = 0; +constexpr unsigned int DIFF_PROCESS = 1; + +boost::process::context getDefaultContext() { + boost::process::context context; + + context.environment = boost::process::self::get_environment(); + context.stdout_behavior = boost::process::capture_stream(); + context.stdin_behavior = boost::process::capture_stream(); + + return context; +} + +} + +namespace tracking { + +ChangeTracker::ChangeTracker(utility::Logger* logger): + logger_(logger), + children_() { } + +ChangeTracker::~ChangeTracker() { + for ( auto&& tracked : this->children_ ) { + std::get(tracked)->get_stdin().close(); + + this->logger_->forward(std::get(tracked)->get_stdout()); + + tracked.second->wait(); + } +} + +bool ChangeTracker::is_tracked(const std::string& file_path) const { + return this->children_.find(file_path) != this->children_.end(); +} + +// Begins tracking changes to a file reachable by a given path +// +// The actual tracking is performed by a `diff` instance that is +// spawned by this method and managed by this class. +// As `diff` is called as a new subprocess and because there is no +// straight forward way for checking / enforcing if it has already +// completed reading the initial contents of the file the command +// is structured in the following sequence: +// +// diff -p - $file_path +// +// This means that reading the final file contents is delegated to +// `diff` while the initial file contents are read by this method +// and written to `diff`'s standard input. +// +// If the `-` and `$file_path` arguments were exchanged there would +// be no way to: +// - be sure the initial contents are read before the changing +// syscall that triggered this tracking in the first place is +// performed +// - be sure that the initial file contents are read completly +// as `diff` seemingly only reads the first block of the first +// file provided if the second file argument is standard input +// +bool ChangeTracker::track(const std::string& file_path) { + auto result = this->children_.emplace( + file_path, + std::make_unique( + boost::process::launch_shell("diff -p - " + file_path, getDefaultContext()) + ) + ); + + if ( std::get(result) ) { + boost::filesystem::ifstream file( + std::get(*result.first) + ); + + if ( file.is_open() ) { + std::get(*result.first)->get_stdin() << file.rdbuf(); + } + + return true; + } else { + return false; + } +} + +} diff --git a/src/tracking/change_tracker.h b/src/tracking/change_tracker.h new file mode 100644 index 0000000..54af4f7 --- /dev/null +++ b/src/tracking/change_tracker.h @@ -0,0 +1,32 @@ +#ifndef CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ +#define CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ + +#include + +#include + +#include "utility/logger.h" + +namespace tracking { + +class ChangeTracker { + public: + ChangeTracker(utility::Logger*); + ~ChangeTracker(); + + bool is_tracked(const std::string&) const; + + bool track(const std::string&); + + private: + utility::Logger* const logger_; + + std::unordered_map< + std::string, std::unique_ptr + > children_; + +}; + +} + +#endif // CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ -- cgit v1.2.3