Skip to content

Commit 92b7739

Browse files
awelcronny-mystenamnn
authored
[docs] Added documentation for dependency overrides (#11253)
## Description A description of how recently landed (#11181) dependency overrides work. Please let me know if you need this changes, extended, etc. I am also not sure if this should be a separate file (as it is intended for now) or if it should be folded into an existing document (e.g., https://github.com/MystenLabs/sui/blob/main/doc/src/build/package-upgrades.md), and if the former is the case, if there is any additional work required to have it properly displayed on the developer portal. ## Test Plan It's just the docs --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [x] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes --------- Co-authored-by: ronny-mysten <[email protected]> Co-authored-by: Ashok Menon <[email protected]>
1 parent ddfe4ff commit 92b7739

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Dependency Overrides
3+
---
4+
5+
One of the main features of the Move programming language used to program Sui smart contracts is code reuse. Packages implementing commonly used functionality, such as various cryptographic algorithms, can be simply reused by other developers that require this kind of functionality in their projects. As part of the package's lifecycle, its developers have the ability to [upgrade](./package-upgrades.md) a package to a newer version (e.g., to fix bugs or provide additional functionality), possibly multiple times. This naturally leads to a situation where some "user" packages may depend on one version of a "library" package while other "user" packages may depend on another.
6+
7+
A package might depend on another package _directly_ or _indirectly_ (also called _transitively_). A direct dependency is specified in the "user" package's [manifest](./move/manifest.md) file and its version is directly controlled by the developer of the "user" package. Clearly these directly dependent packages might have dependencies of their own, and these dependencies become indirect dependencies of the "user" package if they are not also specified in the "user" package's manifest file.
8+
9+
10+
As long as all versions of all (directly or indirectly) dependent packages are the same, no further action on the side of the "user" package's developer is required. Unfortunately, this is not always the case. Consider the following example of the `user` package directly depending on two "library" packages: `vault` and `currency` (these are not real packages and their URLs do not exist). The (simplified) manifest file of the `user` package would then resemble the following:
11+
12+
```move
13+
[package]
14+
name = "user"
15+
version = "1.0.0"
16+
17+
[dependencies]
18+
vault = { git = "https://github.com/vault_org/vault.git" }
19+
currency = { git = "https://github.com/currency_org/currency.git" }
20+
```
21+
22+
Further consider that both `vault` and `currency` depend on another "library" package, `crypto`, but each of them depends on a different version (`crypto` becomes an indirect dependency of the `user` package). Their respective manifest files could then resemble the following:
23+
24+
```move
25+
[package]
26+
name = "vault"
27+
version = "1.0.0"
28+
29+
[dependencies]
30+
crypto = { git = "https://github.com/crypto.org/crypto.git" , rev = "v1.0.0"}
31+
```
32+
33+
```move
34+
[package]
35+
name = "currency"
36+
version = "2.0.0"
37+
38+
[dependencies]
39+
crypto = { git = "https://github.com/crypto.org/crypto.git" , rev = "v2.0.0"}
40+
```
41+
42+
This situation represents the [_diamond dependency conflict_](https://jlbp.dev/what-is-a-diamond-dependency-conflict) where two indirect dependencies in turn depend on different versions of the same package. If all packages involved are developed independently, then the developer of the `user` package has a problem -- the Move compiler cannot discern which version of the `crypto` package to use and, as a result, building of the `user` package fails.
43+
44+
To resolve these types of problems, developers can _override_ indirect dependencies of the packages they develop. In other words, we provide a mechanism that the developer can use to specify a single version of a dependent package to be used during the build process. This can be done by introducing a _dependency override_ in the manifest file of the developed package. In the case of our running example, developer of the `user` package might decide that all dependent packages should use version `2.0.0` of the `crypto` package (note that it is the same as specified in the manifest file of the `currency` package but could be a version not used by any of the dependencies, for example `3.0.0`). At a technical level, in order to enforce a dependency override, a developer of a "user" package has to put a dependency with a chosen version in their own manifest file, with the addition of the `override` flag set to `true`. The manifest file of the `user` package correcting the diamond dependency conflict in our running example would resemble the following:
45+
46+
```move
47+
[package]
48+
name = "user"
49+
version = "1.0.0"
50+
51+
[dependencies]
52+
vault = { git = "https://github.com/vault_org/vault.git" }
53+
currency = { git = "https://github.com/currency_org/currency.git" }
54+
crypto = { git = "https://github.com/crypto.org/crypto.git" , rev = "v2.0.0" , override = true }
55+
```
56+
57+
Note that overriding transitive dependencies in such a manner might not always be successful. In particular, the `vault` package in our example might truly depend on the functionality of the `crypto` package that is only available in version `1.0.0` of this package (e.g, was removed in later package revisions), in which case the build would also be unsuccessful. By offering the ability to enforce dependency overrides we merely put another tool into the developer's toolbox in the hope that it would allow resolution of transitive dependency conflicts in the majority of cases.

0 commit comments

Comments
 (0)