TransferStreamHierarchy.py #1

  • //
  • guest/
  • sven_erik_knop/
  • P4Pythonlib/
  • scripts/
  • Transfer/
  • TransferStreamHierarchy.py
  • View
  • Commits
  • Open Download .zip Download (4 KB)
from __future__ import print_function
import P4
from enum import Enum
import sys
import logging
import argparse

class StreamType(Enum):
    MAIN = 'mainline'
    VIRTUAL = 'virtual'
    DEVELOP = 'development'
    RELEASE = 'release'
    TASK = 'task'

stream_cache = {}

class Stream:
    def __init__(self, stream: dict):
        self.name = stream["Name"]
        self.stream = stream["Stream"]

        if stream["Parent"] == "none":
            self.parent = None
        else:
            if stream["Parent"] in stream_cache:
                self.parent = stream_cache[stream["Parent"]]
            else:
                raise Exception("Cannot find {} in stream_cache".format(self.parent))

        self.stream_type = StreamType(stream["Type"])
        self.options = stream["Options"]
        self.owner = stream["Owner"]

        self.description = stream["desc"]

        self.substreams = []
        self.developmentStreams = []
        self.releaseStreams = []
        self.virtualStreams = []
        self.taskStreams = []

        self.stream_map = {StreamType.DEVELOP: self.developmentStreams,
                           StreamType.RELEASE: self.releaseStreams,
                           StreamType.VIRTUAL: self.virtualStreams,
                           StreamType.TASK: self.taskStreams}

        if self.parent:
            self.parent.add_sub_stream(self)

        # add this stream to the cache for faster lookup
        stream_cache[self.stream] = self

    def add_sub_stream(self, stream):
        self.substreams.append(stream)
        self.stream_map[stream.stream_type].append(stream)

    def __str__(self):
        output = "Stream {}\n".format(self.stream)
        for st in self.developmentStreams:
            output += "  Develop {}\n".format(st)
        for st in self.releaseStreams:
            output += "  Release {}\n".format(st)
        for st in self.virtualStreams:
            output += "  Virtual {}\n".format(st)
        for st in self.taskStreams:
            output += "  Task {}\n".format(st)

        return output


class StreamHierarchy:
    def __init__(self, **kargs):
        self.p4 = P4.P4()

        if kargs["port"]:
            self.p4.port = kargs["port"]
        if kargs["user"]:
            self.p4.user= kargs["user"]

        self.target = P4.P4()
        self.target.port = kargs["target"]
        if kargs["target_user"]:
            self.target.user = kargs["target_user"]
        else:
            self.target.user = self.p4.user

        #self.p4.logger = logging.getLogger("P4")
        #self.p4.logger.setLevel(logging.INFO)
        #self.p4.logger.addHandler(logging.StreamHandler())

    def retrieve_hierarchy(self, name: str):
        with self.p4.connect():
            self.mainline = self.get_stream_by_name(name)
            self.get_stream_by_base_parent(self.mainline)

    def get_stream_by_name(self, name: str) -> Stream:
        stream_data = self.p4.run_streams("-F", "Stream={}".format(name))
        if stream_data:
            return Stream(stream_data[0])
        else:
            raise Exception("Stream {} not found".format(name))

    def get_stream_by_base_parent(self, parent: Stream):
        stream_data = self.p4.run_streams("-F", "baseParent={}".format(parent.stream))
        for st in stream_data:
            stream = Stream(st)

    def create_stream(self, stream : Stream):
        st = self.target.fetch_stream('-t', stream.stream_type.value, stream.stream)

        st._options = stream.options
        st._parent = stream.parent.stream if stream.parent else "none"
        st._owner = stream.owner
        st._description = stream.description

        self.target.save_stream(st)

    def transfer_streams(self):
        with self.target.connect():
            self.create_stream(self.mainline)
            for st in self.mainline.substreams:
                self.create_stream(st)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description="TransferStreams",
        epilog="Copyright (C) 2017 Sven Erik Knop, Perforce Software Ltd"
    )

    parser.add_argument("-p", "--port", help="P4PORT")
    parser.add_argument("-u", "--user", help="P4USER")
    parser.add_argument("-t", "--target", help="Target P4PORT", required=True)
    parser.add_argument("-U", "--target-user", help="Target P4USER")
    parser.add_argument("mainstream")

    args = parser.parse_args()

    mainStreamName = args.mainstream
    hierarchy = StreamHierarchy(**vars(args))
    hierarchy.retrieve_hierarchy(mainStreamName)

    hierarchy.transfer_streams()

# Change User Description Committed
#4 23700 Sven Erik Knop Completed test cases for Stream Transfer, including rename.

Good to go, no further changes required from my point of view.
#3 23699 Sven Erik Knop Always create test cases.
Found a couple of nasty bugs already.

Direct and indirect transfers are tested and seem to work fine. I am going to add a few more tests,
specifically but not exclusive to renames.
#2 23623 Sven Erik Knop Updated to enable renaming of target streams
#1 23587 Sven Erik Knop Renamed to Transfer
//guest/sven_erik_knop/P4Pythonlib/scripts/Transfer/ShowStreamHierarchy.py
#1 23586 Sven Erik Knop Little tool to transfer stream hierarchies