sapling/eden/fs/inodes/Dirstate.h
Michael Bolin 5cf1692782 Add new Thrift API: hgClearDirstate(mountPoint)
Summary:
When Hg tells the `dirstate` to `clear()`, we should also clear out any data we
have on the server for the `Dirstate`.

As it stands, the way we subclass `dirstate`, it does not appear like `clear()`
should be called, in practice, though one thing that could call it is
`hg debugrebuilddirstate`. It is probably good for us to have an RPC lying
around that we can use to reset the `Dirstate.`

Reviewed By: wez

Differential Revision: D5675298

fbshipit-source-id: 38926cfd93f4f83e4c28910f812a693cb32e423a
2017-08-22 16:50:24 -07:00

143 lines
4.6 KiB
C++

/*
* Copyright (c) 2016-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.
*
*/
#pragma once
#include <folly/Optional.h>
#include <folly/Synchronized.h>
#include <folly/experimental/StringKeyedUnorderedMap.h>
#include "eden/fs/inodes/DirstatePersistence.h"
#include "eden/fs/inodes/InodePtrFwd.h"
#include "eden/fs/inodes/gen-cpp2/hgdirstate_types.h"
#include "eden/fs/model/Tree.h"
#include "eden/fs/service/gen-cpp2/EdenService.h"
#include "eden/fs/utils/PathFuncs.h"
namespace facebook {
namespace eden {
class ClientConfig;
class EdenMount;
class InodeBase;
class ObjectStore;
class Tree;
class TreeInode;
namespace fusell {
class InodeBase;
class MountPoint;
}
/**
* Returns the single-char representation of the status used by `hg status`.
* Note that this differs from the corresponding entry in the _VALUES_TO_NAMES
* map for a Thrift enum.
*/
char hgStatusCodeChar(StatusCode code);
struct DirstateAddRemoveError {
DirstateAddRemoveError(RelativePathPiece p, folly::StringPiece s)
: path{p}, errorMessage{s.str()} {}
RelativePath path;
std::string errorMessage;
};
inline bool operator==(
const DirstateAddRemoveError& lhs,
const DirstateAddRemoveError& rhs) {
return lhs.path == rhs.path && lhs.errorMessage == rhs.errorMessage;
}
inline bool operator!=(
const DirstateAddRemoveError& lhs,
const DirstateAddRemoveError& rhs) {
return !(lhs == rhs);
}
std::ostream& operator<<(std::ostream& os, const DirstateAddRemoveError& error);
std::ostream& operator<<(std::ostream& os, const ThriftHgStatus& status);
/**
* This is designed to be a simple implemenation of an Hg dirstate. It's
* "simple" in that every call to `getStatus()` walks the entire overlay to
* determine which files have been added/modified/removed, and then compares
* those files with the base commit to determine the appropriate Hg status code.
*
* Ideally, we would cache information between calls to `getStatus()` to make
* this more efficient, but this seems like an OK place to start. Once we have
* a complete implementation built that is supported by a battery of tests, then
* we can try to optimize things.
*
* For the moment, let's assume that we have the invariant that every file that
* has been modified since the "base commit" exists in the overlay. This means
* that we do not allow a non-commit snapshot to remove files from the overlay.
* Rather, the only time the overlay gets "cleaned up" is in response to a
* commit or an update.
*
* This may not be what we want in the long run, but we need to get basic
* Mercurial stuff working first before we can worry about snapshots.
*/
class Dirstate {
public:
explicit Dirstate(EdenMount* mount);
~Dirstate();
/**
* Get the status information about files that are changed.
*
* This is used for implementing "hg status". Returns the data as a thrift
* structure that can be returned to the eden hg extension.
*
* @param listIgnored Whether or not to report information about ignored
* files.
*/
ThriftHgStatus getStatus(bool listIgnored) const;
/**
* Clean up the Dirstate after the current commit has changed.
*
* This removes Add and Remove directives if the corresponding files have
* been added or removed in the new source control state.
*/
folly::Future<folly::Unit> onSnapshotChanged(const Tree* rootTree);
/** Clears out the data structures associated with this Dirstate. */
void clear();
hgdirstate::DirstateTuple hgGetDirstateTuple(
const RelativePathPiece filename);
void hgSetDirstateTuple(
const RelativePathPiece filename,
const hgdirstate::DirstateTuple* tuple);
bool hgDeleteDirstateTuple(const RelativePathPiece filename);
std::unordered_map<RelativePath, hgdirstate::DirstateTuple>
hgGetNonnormalFiles() const;
void hgCopyMapPut(
const RelativePathPiece dest,
const RelativePathPiece source);
RelativePath hgCopyMapGet(const RelativePathPiece dest) const;
folly::StringKeyedUnorderedMap<RelativePath> hgCopyMapGetAll() const;
private:
/**
* If `filename` exists in the manifest as a file (not a directory), returns
* the mode of the file as recorded in the manifest.
*/
folly::Optional<mode_t> isInManifestAsFile(
const RelativePathPiece filename) const;
/** The EdenMount object that owns this Dirstate */
EdenMount* const mount_{nullptr};
DirstatePersistence persistence_;
folly::Synchronized<DirstateData> data_;
};
}
}