sapling/eden/fs/model/Tree.h
Andrey Chursin 0af2511a3f separate out ObjectId [proxy hash removal 1/n]
Summary:
The goal of this stack is to remove Proxy Hash type, but to achieve that we need first to address some tech debt in Eden codebase.

For the long time EdenFs had single Hash type that was used for many different use cases.

One of major uses for Hash type is identifies internal EdenFs objects such as blobs, trees, and others.

We seem to reach agreement that we need a different type for those identifiers, so we introduce separate ObjectId type in this diff to denote new identifier type and replace _some_ usage of Hash with ObjectId.

We still retain original Hash type for other use cases.

Roughly speaking, this is how this diff separates between Hash and ObjectId:

**ObjectId**:
* Everything that is stored in local store(blobs, trees, commits)

**Hash20**:
* Explicit hashes(Sha1 of the blob)
* Hg identifiers: manifest id and blob hg ig

For now, in this diff ObjectId has exactly same content as Hash, but this will change in the future diffs. Doing this way allows to keep diff size manageable, while migrating to new ObjectId right away would produce insanely large diff that would be both hard to make and review.

There are few more things that needs to be done before we can get to the meat of removing proxy hashes:

1) Replace include Hash.h with ObjectId.h where needed
2) Remove Hash type, explicitly rename rest of Hash usages to Hash20
3) Modify content of ObjectId to support new use cases
4) Modify serialized metadata and possibly other places that assume ObjectId size is fixed and equal to Hash20 size

Reviewed By: chadaustin

Differential Revision: D31316477

fbshipit-source-id: 0d5e4460a461bcaac6b9fd884517e129aeaf4baf
2021-10-01 10:25:46 -07:00

96 lines
2.5 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#pragma once
#include <algorithm>
#include <vector>
#include "eden/fs/model/Hash.h"
#include "eden/fs/model/TreeEntry.h"
namespace facebook::eden {
class Tree {
public:
explicit Tree(
std::vector<TreeEntry>&& entries,
const ObjectId& hash = ObjectId())
: hash_(hash), entries_(std::move(entries)) {}
const ObjectId& getHash() const {
return hash_;
}
/**
* An estimate of the memory footprint of this tree. Called by ObjectCache to
* limit the number of cached trees in memory at a time.
*/
size_t getSizeBytes() const;
const std::vector<TreeEntry>& getTreeEntries() const {
return entries_;
}
const TreeEntry& getEntryAt(size_t index) const {
return entries_.at(index);
}
const TreeEntry* getEntryPtr(PathComponentPiece path) const {
auto iter = std::lower_bound(
entries_.cbegin(),
entries_.cend(),
path,
[](const TreeEntry& entry, PathComponentPiece piece) {
return entry.getName() < piece;
});
if (UNLIKELY(iter == entries_.cend() || iter->getName() != path)) {
#ifdef _WIN32
// On Windows we need to do a case insensitive lookup for the file and
// directory names. For performance, we will do a case sensitive search
// first which should cover most of the cases and if not found then do a
// case sensitive search.
const auto& fileName = path.stringPiece();
for (const auto& entry : entries_) {
if (entry.getName().stringPiece().equals(
fileName, folly::AsciiCaseInsensitive())) {
return &entry;
}
}
#endif
return nullptr;
}
return &*iter;
}
const TreeEntry& getEntryAt(PathComponentPiece path) const {
auto entry = getEntryPtr(path);
if (!entry) {
throw std::out_of_range(
folly::to<std::string>(path, " is not present in this Tree"));
}
return *entry;
}
std::vector<PathComponent> getEntryNames() const {
std::vector<PathComponent> results;
results.reserve(entries_.size());
for (const auto& entry : entries_) {
results.emplace_back(entry.getName());
}
return results;
}
private:
const ObjectId hash_;
const std::vector<TreeEntry> entries_;
};
bool operator==(const Tree& tree1, const Tree& tree2);
bool operator!=(const Tree& tree1, const Tree& tree2);
} // namespace facebook::eden