| // 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; |
| } |