mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
2fedc3bcea
Summary: Change getScmStatus() so that callers must explicitly specify the commit to diff against. This should help avoid race conditions around commit or checkout operations where the parent commit has just changed and eden returns status information against a commit that wasn't what the client was expecting. This should still maintain backwards compatibility with older clients that do not send this parameter yet: we will simply receive the hash as an empty string in this case, and we still provide the old behavior in this case. Reviewed By: wez Differential Revision: D7512338 fbshipit-source-id: 1fb4645dda13b9108c66c2daaa802ea3445ac5f2
115 lines
3.4 KiB
C++
115 lines
3.4 KiB
C++
/*
|
|
* Copyright (c) 2017-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
*/
|
|
#include "eden/fs/inodes/Differ.h"
|
|
#include <folly/Optional.h>
|
|
#include <folly/Synchronized.h>
|
|
#include <folly/experimental/logging/xlog.h>
|
|
#include <folly/futures/Future.h>
|
|
#include "eden/fs/inodes/EdenMount.h"
|
|
#include "eden/fs/inodes/InodeDiffCallback.h"
|
|
#include "eden/fs/model/Tree.h"
|
|
#include "eden/fs/model/TreeEntry.h"
|
|
#include "eden/fs/store/ObjectStore.h"
|
|
#include "eden/fs/utils/PathFuncs.h"
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
namespace {
|
|
class ThriftStatusCallback : public InodeDiffCallback {
|
|
public:
|
|
void ignoredFile(RelativePathPiece path) override {
|
|
data_.wlock()->emplace(path.stringPiece().str(), ScmFileStatus::IGNORED);
|
|
}
|
|
|
|
void untrackedFile(RelativePathPiece path) override {
|
|
data_.wlock()->emplace(path.stringPiece().str(), ScmFileStatus::ADDED);
|
|
}
|
|
|
|
void removedFile(
|
|
RelativePathPiece path,
|
|
const TreeEntry& /* sourceControlEntry */) override {
|
|
data_.wlock()->emplace(path.stringPiece().str(), ScmFileStatus::REMOVED);
|
|
}
|
|
|
|
void modifiedFile(
|
|
RelativePathPiece path,
|
|
const TreeEntry& /* sourceControlEntry */) override {
|
|
data_.wlock()->emplace(path.stringPiece().str(), ScmFileStatus::MODIFIED);
|
|
}
|
|
|
|
void diffError(RelativePathPiece path, const folly::exception_wrapper& ew)
|
|
override {
|
|
// TODO: It would be nice to have a mechanism to return error info as part
|
|
// of the thrift result.
|
|
XLOG(WARNING) << "error computing status data for " << path << ": "
|
|
<< folly::exceptionStr(ew);
|
|
}
|
|
|
|
/**
|
|
* Extract the ScmStatus object from this callback.
|
|
*
|
|
* This method should be called no more than once, as this destructively
|
|
* moves the results out of the callback. It should only be invoked after
|
|
* the diff operation has completed.
|
|
*/
|
|
ScmStatus extractStatus() {
|
|
ScmStatus status;
|
|
|
|
{
|
|
auto data = data_.wlock();
|
|
status.entries.swap(*data);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
private:
|
|
folly::Synchronized<std::map<std::string, ScmFileStatus>> data_;
|
|
};
|
|
} // unnamed namespace
|
|
|
|
char scmStatusCodeChar(ScmFileStatus code) {
|
|
switch (code) {
|
|
case ScmFileStatus::ADDED:
|
|
return 'A';
|
|
case ScmFileStatus::MODIFIED:
|
|
return 'M';
|
|
case ScmFileStatus::REMOVED:
|
|
return 'R';
|
|
case ScmFileStatus::IGNORED:
|
|
return 'I';
|
|
}
|
|
throw std::runtime_error(folly::to<std::string>(
|
|
"Unrecognized ScmFileStatus: ",
|
|
static_cast<typename std::underlying_type<ScmFileStatus>::type>(code)));
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const ScmStatus& status) {
|
|
os << "{";
|
|
for (const auto& pair : status.get_entries()) {
|
|
os << scmStatusCodeChar(pair.second) << " " << pair.first << "; ";
|
|
}
|
|
os << "}";
|
|
return os;
|
|
}
|
|
|
|
folly::Future<std::unique_ptr<ScmStatus>>
|
|
diffMountForStatus(const EdenMount* mount, Hash commitHash, bool listIgnored) {
|
|
auto callback = std::make_unique<ThriftStatusCallback>();
|
|
auto callbackPtr = callback.get();
|
|
return mount->diff(callbackPtr, commitHash, listIgnored)
|
|
.then([callback = std::move(callback)]() {
|
|
return std::make_unique<ScmStatus>(callback->extractStatus());
|
|
});
|
|
}
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|