Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix existential issue with SCM aware queries
Summary: This was a bit of a thorny issue to run down. What was happening was this: when source control aware mode is enabled we subvert the normal recency index and use the `pathGenerator` rather than the `timeGenerator`. We pass the list of files that we got back from the source control system to the path generator and let it evaluate the query based on information that we've observed in the InMemoryView. If watchman has never observed some components of the paths returned by the source control query, such as in the case where watchman was restarted after checking out the revision, and we're asked about changes since an earlier hash, the `pathGenerator` will not be able to furnish information about the paths returned by source control. This means that we are potentially inaccurate for files that exist on the filesystem (although we will likely soon observe the current state of those files), but more critically, we cannot return information about files that were deleted in between the commits in the query range. The resolution is not to use the InMemoryView as the source of information about these files. This diff adds a LocalFileResult for just this purpose; this is an implementation of the FileResult class that knows how to stat the local filesystem as needed to furnish the metadata that may be needed by the query. I'm not thrilled that it needs to stat the files, but this the simplest way to obtain correct results and we can figure out if we need to do better than this in practice as a follow up. I've also broken out the guts of `ContentHashCache::computeHashImmediate` as a static function so that we can call it from `LocalFileResult`. Ideally we'd find a way to plumb in the cache that is held in the `InMemoryView`, but we're operating at a different layer and cannot guarantee that it is present; it isn't present for Eden and we still need to solve the hash computation issue for Eden. Those are out of scope wrt. resolving this issue in the short term. Reviewed By: simpkins Differential Revision: D7142088 fbshipit-source-id: 35b7d7745e30adabb8b9a7b3713d6ba3500b3552
- Loading branch information
1 parent
f6cbdc4
commit 72950c2
Showing
8 changed files
with
175 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#include "LocalFileResult.h" | ||
#include "ContentHash.h" | ||
#include "watchman_error_category.h" | ||
namespace watchman { | ||
|
||
LocalFileResult::LocalFileResult( | ||
const std::shared_ptr<w_root_t>& root, | ||
w_string_piece path, | ||
w_clock_t clock) | ||
: root_(root), path_(path.asWString()), clock_(clock) {} | ||
|
||
void LocalFileResult::getInfo() const { | ||
if (!needInfo_) { | ||
return; | ||
} | ||
needInfo_ = false; | ||
try { | ||
info_ = getFileInformation(path_.c_str(), root_->case_sensitive); | ||
exists_ = true; | ||
} catch (const std::exception&) { | ||
// Treat any error as effectively deleted | ||
exists_ = false; | ||
} | ||
} | ||
|
||
const watchman::FileInformation& LocalFileResult::stat() const { | ||
getInfo(); | ||
return info_; | ||
} | ||
|
||
w_string_piece LocalFileResult::baseName() const { | ||
return w_string_piece(path_).baseName(); | ||
} | ||
|
||
w_string_piece LocalFileResult::dirName() { | ||
return w_string_piece(path_).dirName(); | ||
} | ||
|
||
bool LocalFileResult::exists() const { | ||
getInfo(); | ||
return exists_; | ||
} | ||
|
||
watchman::Future<w_string> LocalFileResult::readLink() const { | ||
auto absPath = w_string::pathCat({root_->root_path, path_}); | ||
return makeFuture(readSymbolicLink(absPath.c_str())); | ||
} | ||
|
||
const w_clock_t& LocalFileResult::ctime() const { | ||
return clock_; | ||
} | ||
|
||
const w_clock_t& LocalFileResult::otime() const { | ||
return clock_; | ||
} | ||
|
||
watchman::Future<FileResult::ContentHash> LocalFileResult::getContentSha1() { | ||
// TODO: find a way to reference a ContentHashCache instance | ||
// that will work with !InMemoryView based views. | ||
return makeFuture(makeResultWith([&] { | ||
auto absPath = w_string::pathCat({root_->root_path, path_}); | ||
return ContentHashCache::computeHashImmediate(absPath.c_str()); | ||
})); | ||
} | ||
} // namespace watchman |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#pragma once | ||
#include "thirdparty/jansson/jansson.h" | ||
#include "watchman.h" | ||
#include "watchman_query.h" | ||
#include "watchman_string.h" | ||
|
||
namespace watchman { | ||
|
||
/** A FileResult that exists on the local filesystem. | ||
* This differs from InMemoryFileResult in that we don't maintain any | ||
* long-lived persistent information about the file and that the methods of | ||
* this instance will query the local filesystem to discover the information as | ||
* it is accessed. | ||
* We do cache the results of any filesystem operations that we may perform | ||
* for the duration of the lifetime of a given LocalFileResult, but that | ||
* information is not shared beyond that lifetime. | ||
* FileResult objects are typically extremely short lived, existing between | ||
* the point in time at which a file is matched by a query and the time | ||
* at which the file is rendered into the results of the query. | ||
*/ | ||
class LocalFileResult : public FileResult { | ||
public: | ||
LocalFileResult( | ||
const std::shared_ptr<w_root_t>& root_, | ||
w_string_piece path, | ||
w_clock_t clock); | ||
const watchman::FileInformation& stat() const override; | ||
// Returns the name of the file in its containing dir | ||
w_string_piece baseName() const override; | ||
// Returns the name of the containing dir relative to the | ||
// VFS root | ||
w_string_piece dirName() override; | ||
// Returns true if the file currently exists | ||
bool exists() const override; | ||
// Returns the symlink target | ||
watchman::Future<w_string> readLink() const override; | ||
|
||
const w_clock_t& ctime() const override; | ||
const w_clock_t& otime() const override; | ||
|
||
// Returns the SHA-1 hash of the file contents | ||
watchman::Future<FileResult::ContentHash> getContentSha1() override; | ||
|
||
private: | ||
void getInfo() const; | ||
mutable bool needInfo_{true}; | ||
mutable bool exists_{true}; | ||
mutable FileInformation info_; | ||
std::shared_ptr<w_root_t> root_; | ||
w_string path_; | ||
w_clock_t clock_; | ||
}; | ||
|
||
} // namespace watchman |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters