mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
9ace5a2f03
Summary: Mercurial core does this sometimes where it sets the new entries before it removes the old entries. In that case, you might have: old manifest: ``` abc ``` operations: ``` + abc/def - abc ``` If you add `abc/def` to a manifest already containing `abc`, it will throw a `TypeError` today. With this change, we accept this weird state. Test Plan: Update the tests to cover both versions of this scenario (directory was there first vs file was there first). Pass all tests. Reviewers: #fastmanifest, durham Reviewed By: durham Subscribers: durham, mitrandir, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3865617 Signature: t1:3865617:1473897481:4cf4f122dfd3a3759fe84ea167b8cb0e78238bc2
161 lines
4.3 KiB
C++
161 lines
4.3 KiB
C++
// manifest.h - c++ declarations for a single manifest
|
|
//
|
|
// Copyright 2016 Facebook, Inc.
|
|
//
|
|
// This software may be used and distributed according to the terms of the
|
|
// GNU General Public License version 2 or any later version.
|
|
//
|
|
// no-check-code
|
|
|
|
#ifndef REMOTEFILELOG_MANIFEST_H
|
|
#define REMOTEFILELOG_MANIFEST_H
|
|
|
|
#include "pythonutil.h"
|
|
|
|
#include <list>
|
|
#include <stdexcept>
|
|
|
|
class Manifest;
|
|
class ManifestIterator;
|
|
class SortedManifestIterator;
|
|
|
|
#include "manifest_entry.h"
|
|
|
|
/**
|
|
* This class represents a view on a particular Manifest instance. It provides
|
|
* access to the list of files/directories at one level of the tree, not the
|
|
* entire tree.
|
|
*
|
|
* Instances of this class do not own the actual storage of manifest data. This
|
|
* class just provides a view onto that existing storage.
|
|
*
|
|
* If the actual manifest data comes from the store, this class refers to it via
|
|
* a PythonObj, and reference counting is used to determine when it's cleaned
|
|
* up.
|
|
*
|
|
* If the actual manifest data comes from an InMemoryManifest, then the life
|
|
* time of that InMemoryManifest is managed elsewhere, and is unaffected by the
|
|
* existence of Manifest objects that view into it.
|
|
*/
|
|
class Manifest {
|
|
private:
|
|
PythonObj _rawobj;
|
|
|
|
std::list<ManifestEntry> entries;
|
|
std::list<ManifestEntry *> mercurialSortedEntries;
|
|
|
|
public:
|
|
Manifest() {
|
|
}
|
|
|
|
Manifest(PythonObj &rawobj);
|
|
|
|
/**
|
|
* Returns a deep copy of this Manifest.
|
|
*/
|
|
Manifest *copy();
|
|
|
|
ManifestIterator getIterator();
|
|
|
|
SortedManifestIterator getSortedIterator();
|
|
|
|
/**
|
|
* Returns an iterator correctly positioned for a child of a given
|
|
* filename and directory/file status. If a child with the same name
|
|
* and directory/file status already exists, *exacthit will be set to
|
|
* true. Otherwise, it will be set to false.
|
|
*/
|
|
std::list<ManifestEntry>::iterator findChild(
|
|
const char *filename, const size_t filenamelen, bool isdir,
|
|
bool *exacthit);
|
|
|
|
/**
|
|
* Adds a child with a given name.
|
|
* @param iterator iterator for this->entries, correctly positioned for
|
|
* the child.
|
|
* @param filename
|
|
* @param filenamelen
|
|
*/
|
|
ManifestEntry *addChild(std::list<ManifestEntry>::iterator iterator,
|
|
const char *filename, const size_t filenamelen, const char *node,
|
|
const char *flag);
|
|
|
|
/**
|
|
* Adds a deep copy of the given ManifestEntry as a child.
|
|
*/
|
|
ManifestEntry *addChild(std::list<ManifestEntry>::iterator iterator,
|
|
ManifestEntry *otherChild);
|
|
|
|
int children() const {
|
|
return entries.size();
|
|
}
|
|
|
|
/**
|
|
* Removes a child with referenced by the iterator.
|
|
* @param iterator iterator for this->entries, correctly positioned for
|
|
* the child.
|
|
*/
|
|
void removeChild(
|
|
std::list<ManifestEntry>::iterator iterator) {
|
|
this->entries.erase(iterator);
|
|
|
|
// invalidate the mercurial-ordered list of entries
|
|
this->mercurialSortedEntries.clear();
|
|
}
|
|
|
|
/**
|
|
* Serializes the current manifest into the given string. The serialization
|
|
* format matches upstream Mercurial's Manifest format and is appropriate
|
|
* for putting in a store.
|
|
*/
|
|
void serialize(std::string &result);
|
|
};
|
|
|
|
/**
|
|
* Class that represents an iterator over the entries of an individual
|
|
* manifest.
|
|
*/
|
|
class ManifestIterator {
|
|
private:
|
|
std::list<ManifestEntry>::iterator iterator;
|
|
std::list<ManifestEntry>::const_iterator end;
|
|
public:
|
|
ManifestIterator() {
|
|
}
|
|
|
|
ManifestIterator(
|
|
std::list<ManifestEntry>::iterator iterator,
|
|
std::list<ManifestEntry>::const_iterator end);
|
|
|
|
ManifestEntry *next();
|
|
|
|
ManifestEntry *currentvalue() const;
|
|
|
|
bool isfinished() const;
|
|
};
|
|
|
|
/**
|
|
* Class that represents an iterator over the entries of an individual
|
|
* manifest, sorted by mercurial's ordering.
|
|
*/
|
|
class SortedManifestIterator {
|
|
private:
|
|
std::list<ManifestEntry *>::iterator iterator;
|
|
std::list<ManifestEntry *>::const_iterator end;
|
|
public:
|
|
SortedManifestIterator() {
|
|
}
|
|
|
|
SortedManifestIterator(
|
|
std::list<ManifestEntry *>::iterator iterator,
|
|
std::list<ManifestEntry *>::const_iterator end);
|
|
|
|
ManifestEntry *next();
|
|
|
|
ManifestEntry *currentvalue() const;
|
|
|
|
bool isfinished() const;
|
|
};
|
|
|
|
#endif //REMOTEFILELOG_MANIFEST_H
|