blob: 41e848da61fd0fa3d304f28df8ea6a868db3c76c [file] [log] [blame]
// Copyright 2024 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
edition = "2023";
package devtools.skyframe;
option java_multiple_files = true;
option java_package = "com.google.devtools.build.lib.skyframe.serialization.proto";
// This message contains sufficient information to invalidate Bazel file
// dependencies against repository diffs.
//
// The goal is for this data to represent
// `com.google.devtools.build.lib.vfs.FileStateKey.argument` values. However,
// these values are represented within a structure defined by the
// `com.google.devtools.build.lib.skyframe.FileFunction`, meaning that whenever
// a `FileStateKey.argument` is encountered, it implies that its parent
// directory will be present. Therefore, there's going to be significant
// redundancy in the path information.
//
// This redundancy can be exploited for compactness, resulting in this implicit
// representation.
//
// This value is always used in the context of a key-value store (e.g.
// Memcached), where the key is defined as follows. Let E be some
// Memcached-friendly encoding function, (e.g. Base64) and `:` be a delimiter in
// the following (`:` does not occur in Base64, making it a good delimiter). Let
// MTSV be the maximum transitive source version, a version number that is the
// maximum version over all the transitive source files affecting an entry. In
// the case of a file, this includes all source versions of all parent
// directories and any symlinks needed to resolve it. The MTSV is a canonical
// version for the file.
//
// KEY = E(MTSV) : <FileValue.Key.argument path>
//
// Logically, the key consists of the FileValue's MTSV and unresolved path.
// Note, in particular, the path data present in the key does not need to be
// repeated in the value. The parent directory of this key is already the
// `FileValue.Key.argument` path of its parent directory, so that doesn't need
// to be repeated either. The only additional data needed to identify the
// `FileInvalidationData` of its parent is the parent's MTSV, which is included
// as `parent_mtsv`.
//
// In the common case, `FileInvalidationData` is empty and that's sufficient
// information to derive all the paths, assuming that the parent lookups are
// transitively performed. The `FileStateKey.argument` matches the path present
// in the key.
//
// In the presence of symlinks, special logic applies to produce the resolved
// paths. A `symlinks` entry will be present. To unpack the symlink entry, we
// first resolve the parent path as usual. Then, we concatenate the symlink's
// contents to the resolved parent path and syntactically normalize it
// (interpreting things like `..`, `.` using string manipulation). This
// establishes a new path to be recursively resolved. `Symlink` contains another
// `parent_mtsv` for this purpose. The resulting resolved path is another
// implicit `FileStateKey.argument` value. If this path is itself a symlink, the
// process is repeated.
//
// Note that this is only suitable for persisting information about a successful
// build so it ignores symlink cycles.
message FileInvalidationData {
// The following field is populated when the key needs to be abbreviated to
// its fingerprint due to Memcached's key length restriction. This field can
// be used to verify that no fingerprint collision has occurred.
string overflow_key = 1;
// The MTSV used to resolve the parent directory.
//
// Resolution means creating a key from this MTSV and the parent directory of
// the key of this entry, looking up the value and interpreting it.
//
// Optional. Unset in the following two cases.
// 1. When the path has no parent, i.e. contains no '/' separators
// 2. It is a directory and has the common sentinel value, -1.
int64 parent_mtsv = 2;
// This field is repeated, with one entry for each symbolic link encountered
// while resolving the path.
repeated Symlink symlinks = 3;
}
// Invalidation information for a
// `com.google.devtools.build.lib.skyframe.DirectoryListingValue`. Note
// that this is designed for certain repository deltas having no directory
// awareness. This means when a file within the directory changes, there's no
// change notification to the directory itself. The consumer is responsible for
// invalidating this entry when its children change in ways that would affect
// the directory listing, like adding and deleting files or a change in their
// type.
//
// This behaves very similarly to `FileInvalidationData`. The KEY is same except
// that it uses a different delimiter, `;`.
//
// This induces a `FileInvalidationData` at the same path as in the key. The
// resolved path of the `FileInvalidationData` is the real path of this
// directory. NB: this is slightly different from `FileInvalidationData`
// behavior which induces a `FileInvalidationData` entry of its parent.
message DirectoryListingInvalidationData {
// The following field is populated when the key needs to be abbreviated to
// its fingerprint due to Memcached's key length restriction. This field can
// be used to verify that no fingerprint collision has occurred.
string overflow_key = 1;
// MTSV required to resolve the real directory path.
//
// Optional. Only set if this is not the common, sentinel value, -1.
int64 file_mtsv = 2;
}
// Representation of symlinks in `FileInvalidationData`.
message Symlink {
// The contents of the symlink.
//
// This field only stores the path specified within the symlink itself. The
// resolved path of the symlink's parent directory is determined based on its
// position within the `symlinks` field in the `FileInvalidationData` message.
//
// * For the first `Symlink` entry in the list, the parent directory is the
// same as the parent directory of the original file path being resolved.
// * For subsequent `Symlink` entries, the parent directory is the directory
// of the resolved target path of the preceding `Symlink` entry.
//
// Given the resolved parent directory, `contents` appended to that parent
// directory and then syntactically normalized, resulting in a new path.
//
// Required.
string contents = 1;
// The MTSV of the resolved parent directory of this symlink.
//
// This field is optional. It is only set if the resolved path formed by
// combining the `contents` with the parent directory results in a *different*
// parent directory than the one used to resolve the symlink itself and that
// value is not the common sentinel, -1.
//
// Optional.
int64 parent_mtsv = 2;
}