2017-03-21 22:44:21 +03:00
|
|
|
/*
|
2019-06-20 02:58:25 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2017-03-21 22:44:21 +03:00
|
|
|
*
|
2019-06-20 02:58:25 +03:00
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
2017-03-21 22:44:21 +03:00
|
|
|
*/
|
2019-10-11 15:26:59 +03:00
|
|
|
|
2017-03-21 22:44:21 +03:00
|
|
|
#include "eden/fs/service/PrettyPrinters.h"
|
|
|
|
|
2019-01-02 23:55:02 +03:00
|
|
|
#include <folly/Conv.h>
|
2017-03-21 22:44:21 +03:00
|
|
|
#include <ostream>
|
|
|
|
|
2017-03-31 07:24:10 +03:00
|
|
|
namespace {
|
|
|
|
template <typename ThriftEnum>
|
|
|
|
std::ostream& outputThriftEnum(
|
|
|
|
std::ostream& os,
|
|
|
|
ThriftEnum value,
|
|
|
|
folly::StringPiece typeName) {
|
2020-03-28 01:25:07 +03:00
|
|
|
const char* name = apache::thrift::TEnumTraits<ThriftEnum>::findName(value);
|
|
|
|
if (name) {
|
|
|
|
return os << name;
|
2017-03-31 07:24:10 +03:00
|
|
|
} else {
|
2020-03-28 01:25:07 +03:00
|
|
|
return os << typeName << "::" << int(value);
|
2017-03-31 07:24:10 +03:00
|
|
|
}
|
|
|
|
}
|
2019-01-02 23:55:02 +03:00
|
|
|
|
|
|
|
template <typename ThriftEnum>
|
|
|
|
void appendThriftEnum(
|
|
|
|
ThriftEnum value,
|
|
|
|
std::string* result,
|
|
|
|
folly::StringPiece typeName) {
|
2020-03-28 01:25:07 +03:00
|
|
|
const char* name = apache::thrift::TEnumTraits<ThriftEnum>::findName(value);
|
|
|
|
if (name) {
|
|
|
|
result->append(name);
|
2019-01-02 23:55:02 +03:00
|
|
|
} else {
|
2020-03-28 01:25:07 +03:00
|
|
|
result->append(folly::to<std::string>(typeName, "::", int(value)));
|
2019-01-02 23:55:02 +03:00
|
|
|
}
|
|
|
|
}
|
2017-03-31 07:24:10 +03:00
|
|
|
} // unnamed namespace
|
|
|
|
|
2017-03-21 22:44:21 +03:00
|
|
|
namespace facebook {
|
|
|
|
namespace eden {
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& os, ConflictType conflictType) {
|
2020-03-28 01:25:07 +03:00
|
|
|
return outputThriftEnum(os, conflictType, "ConflictType");
|
2017-03-21 22:44:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& os, const CheckoutConflict& conflict) {
|
2020-07-21 21:21:48 +03:00
|
|
|
os << "CheckoutConflict(type=" << *conflict.type_ref() << ", path=\""
|
|
|
|
<< *conflict.path_ref() << "\", message=\"" << *conflict.message_ref()
|
|
|
|
<< "\")";
|
2017-03-21 22:44:21 +03:00
|
|
|
return os;
|
|
|
|
}
|
2017-03-31 07:24:10 +03:00
|
|
|
|
Store Hg dirstate data in Hg instead of Eden.
Summary:
This is a major change to how we manage the dirstate in Eden's Hg extension.
Previously, the dirstate information was stored under `$EDEN_CONFIG_DIR`,
which is Eden's private storage. Any time the Mercurial extension wanted to
read or write the dirstate, it had to make a Thrift request to Eden to do so on
its behalf. The upside is that Eden could answer dirstate-related questions
independently of the Python code.
This was sufficiently different than how Mercurial's default dirstate worked
that our subclass, `eden_dirstate`, had to override quite a bit of behavior.
Failing to manage the `.hg/dirstate` file in a way similar to the way Mercurial
does has exposed some "unofficial contracts" that Mercurial has. For example,
tools like Nuclide rely on changes to the `.hg/dirstate` file as a heuristic to
determine when to invalidate its internal caches for Mercurial data.
Today, Mercurial has a well-factored `dirstatemap` abstraction that is primarily
responsible for the transactions with the dirstate's data. With this split, we can
focus on putting most of our customizations in our `eden_dirstate_map` subclass
while our `eden_dirstate` class has to override fewer methods. Because the
data is managed through the `.hg/dirstate` file, transaction logic in Mercurial that
relies on renaming/copying that file will work out-of-the-box. This change
also reduces the number of Thrift calls the Mercurial extension has to make
for operations like `hg status` or `hg add`.
In this revision, we introduce our own binary format for the `.hg/dirstate` file.
The logic to read and write this file is in `eden/py/dirstate.py`. After the first
40 bytes, which are used for the parent hashes, the next four bytes are
reserved for a version number for the file format so we can manage file format
changes going forward.
Admittedly one downside of this change is that it is a breaking change.
Ideally, users should commit all of their local changes in their existing mounts,
shutdown Eden, delete the old mounts, restart Eden, and re-clone.
In the end, this change deletes a number of Mercurial-specific code and Thrift
APIs from Eden. This is a better separation of concerns that makes Eden more
SCM-agnostic. For example, this change removes `Dirstate.cpp` and
`DirstatePersistance.cpp`, replacing them with the much simpler and more
general `Differ.cpp`. The Mercurial-specific logic from `Dirstate.cpp` that turned
a diff into an `hg status` now lives in the Mercurial extension in
`EdenThriftClient.getStatus()`, which is much more appropriate.
Note that this reverts the changes that were recently introduced in D6116105:
we now need to intercept `localrepo.localrepository.dirstate` once again.
Reviewed By: simpkins
Differential Revision: D6179950
fbshipit-source-id: 5b78904909b669c9cc606e2fe1fd118ef6eaab95
2017-11-07 06:44:24 +03:00
|
|
|
std::ostream& operator<<(std::ostream& os, ScmFileStatus scmFileStatus) {
|
2020-03-28 01:25:07 +03:00
|
|
|
return outputThriftEnum(os, scmFileStatus, "ScmFileStatus");
|
2017-03-31 07:24:10 +03:00
|
|
|
}
|
2019-01-02 23:55:02 +03:00
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& os, MountState mountState) {
|
2020-03-28 01:25:07 +03:00
|
|
|
return outputThriftEnum(os, mountState, "MountState");
|
2019-01-02 23:55:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void toAppend(MountState mountState, std::string* result) {
|
2020-03-28 01:25:07 +03:00
|
|
|
appendThriftEnum(mountState, result, "MountState");
|
2019-01-02 23:55:02 +03:00
|
|
|
}
|
|
|
|
|
2017-11-04 01:58:04 +03:00
|
|
|
} // namespace eden
|
|
|
|
} // namespace facebook
|