Stream Components

A stream component is similar to an import of default paths because both allow the stream client to have access to files outside of the current stream. An advantage of a stream component is that it avoids the maintenance issues associated with keeping default paths up to date.

Stream Components allow stream client views to include other stream views. Any stream can become a component by being referenced in another stream view.

Components can be nested to arbitrary levels. For example, stream A references component stream B, which references component stream C, which references component stream D.

Note

A stream cannot reference itself as a component, either directly or indirectly through other referenced component streams.

Enabling stream components

By default, the stream components feature is not enabled. To enable this feature, set the dm.stream.components configurable to 1.

Defining readonly stream components

A readonly stream component is defined with this syntax:

component_type component_folder component_stream[@[change | automatic_label]]

such as

readonly dirB //streams/B

where

component_type component_folder component_stream[@[change | automatic_label]]

is readonly, so component files can be synced (and even opened for edit), but cannot be submitted

Specifies a directory prefix for each component view file.

The specified directory is directly under the workspace root directory.

Specifies the name and path of the component stream, which can be pinned to a change or automatic label.

If @change or @automatic_label is specified,

  • the version of the component stream specification at or before the change or label is used

  • any files synced will be at revisions at or before the change or label.

If neither @change nor @automatic_label is specified, the view is not pinned to any change number but instead defaults to the current revision at that time.

StreamAtChange applies to components@change

Important

Do not confuse @change with @head because a StreamAtChange applies to all streams, including those contributing view as Components.

For example, when setting StreamAtChange=86, you are asking for the view at change 86, which includes the streamviews for //str/comp-devDD at change 86 (or before).

Although the spec for the stream might have a component at the head revision when setting StreamAtChange=86, the version limit is at 86, not at head. In this scenario, the value of @change overrides the value of @head.

Examples of stream components

For example, given three streams, //streams/A, //streams/B, and //streams/C,

and //streams/A has a component definition

readonly dirB //streams/B

and //streams/B has a component definition

readonly dirC //streams/C

a client of //streams/A therefore has the views

//streams/A/...  //clientname/...
//streams/B/...  //clientname/dirB/...
//streams/C/...  //clientname/dirB/dirC/...

and a client of //streams/B therefore has the views

//streams/B/...  //clientname/...
//streams/C/...  //clientname/dirC/...

In this example, the client of /streams/A does not need to maintain default paths for //streams/B and //streams/C. Therefore, if //streams/C upgrades its path for a new library version, all the stream views that consume the //streams/C component automatically have access to that new library version.

Tip

For security, the p4 protect protections table remains in force. For example, if a user has //clientname/dirB/dirC/... in the component view, but lacks the read protection for that directory, that user cannot read those files.

source stream and source path type

Suppose that stream A consumes component B, and B consumes component C, and C has a path

import oRead/... //other/oRead/...

This causes a client of A to get the view

//other/oRead/... //clientOfA/dirB/dirC/oRead/...

where A is the stream, C is the source stream, and import is the source path type.

In other words, C is the source stream because C is a component that A consumes.

inheritance and noinherit

Component views are inherited by descendants of the defining stream, unless a descendant has a noinherit ParentView. For example, if a mainline stream consumes two components, the development stream that is a child of that mainline stream also consumes those same two components.

If a descendant stream is converted to have a noinherit ParentView, the component definition is copied to the descendant. In this way, a noinherit ParentView child stream can continue to consume the same components directly as it did by inheritance from its parent prior to conversion to noinherit.

Note

A stream component only affects client views. Branch views are not affected by stream components, so integrations between parent and child are unaffected by component definitions.

additional information

See also the p4 help stream command-line output.

Writable components

Starting in 2022.2, a stream consumer can set the component_type to readonly, writeimport+, or writeall. Both writeimport+, or writeall allow stream consumer clients to open for edit and submit changes to files in certain paths in the stream component:

writeimport+ writeall
applies solely to import+ paths in the stream component applies to share, isolate, or import+ paths in the stream component

See the path types for the Paths field of p4 stream in Helix Core Command-Line (P4) Reference.

defining writeable stream components

A writeable stream component is defined with this syntax:

component_type component_folder component_stream

such as

writeimport+ dirWI //streams/W1

or

writeall dirWA //streams/WA

where

component_type component_folder component_stream

is writeimport+ or writeall

Specifies a directory prefix for each component view file.

The specified directory is directly under the workspace root directory.

Specifies the name and path of the component stream.

Writeable stream components do NOT support @change or @automatic_label, so the view is not pinned to any change number but instead defaults to the head version.

effective component type and the end component

The effective component type in a chain of components of different types is whichever component_type is the most restrictive for views originating from the end component in the chain.

The end component is the final component in a chain of components. In the Examples of stream components above where stream A consumes B, and B consumes C, the end component is C.

Consider these two cases:

  • If stream A defines a writeall component B, and B defines a readonly component C, the views that originate from paths in the end component, C, are readonly

    • Because readonly is the most restrictive component_type, if readonly exists at any location in the chain, readonly applies throughout the chain when the view originates from the end component

  • If stream A defines a writeimport+ component B, and B defines a writeall component C, the views in A that originate from share or isolate paths in the end component, C, are readonly, while import+ paths in C are writable.

    • Because writeimport+ is more restrictive than writeall, it is writeimport+ that applies throughout the chain when the view originates from the end component, and writeimport+ prevents writing to share or isolate paths.

Viewing imported files

The --streamviews option of p4 dirs, p4 files, and p4 fstat reports files and directories from stream Paths and Components. Imported files are represented as symbolic links under the stream depot path.

For example, if stream C has the import, and there is one actual file in each of A, B, and C

then

$ p4 stream -o //root/C

includes in its output:

Paths:
    share ...
    import oRead/... //other/oRead/...

and

$ p4 sync -f

outputs:

//root/A/a1#1 - refreshing /home/maria/test/components/client/a1
//root/B/b1#1 - refreshing /home/maria/test/components/client/dirB/b1
//root/C/c1#1 - refreshing /home/maria/test/components/client/dirB/dirC/c1
//other/oRead/or1#1 - refreshing /home/maria/test/components/client/dirB/dirC/oRead/or1

and

$ p4 files --streamviews //root/A/...

outputs:

//root/A/dirB/dirC/oRead/or1#1 (mapped to //other/oRead/or1) - add change 4 (text)
//root/A/a1#1 - add change 8 (text)
//root/A/dirB/b1#1 (mapped to //root/B/b1) - add change 9 (text)
//root/A/dirB/dirC/c1#1 (mapped to //root/C/c1) - add change 10 (text)

The --streamviews option is convenient because you can view this report without having to create a new workspace.