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.rename = None if kargs["rename"]: self.rename = kargs["rename"] 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", "Parent={}".format(parent.stream)) for st in stream_data: stream = Stream(st) self.get_stream_by_base_parent(stream) 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) for st in stream.substreams: self.create_stream(st) def rename_stream(self, stream : Stream, base : str, rename : str): stream.stream = stream.stream.replace(base, rename) for st in stream.substreams: self.rename_stream(st, base, rename) def rename_streams(self): base = self.rename[0] rename = self.rename[1] self.rename_stream(self.mainline, base, rename) def transfer_streams(self): if self.rename: self.rename_streams() with self.target.connect(): self.create_stream(self.mainline) 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("-r", "--rename", nargs=2, help="'old basename' 'new basename'") parser.add_argument("mainstream") args = parser.parse_args() mainStreamName = args.mainstream hierarchy = StreamHierarchy(**vars(args)) hierarchy.retrieve_hierarchy(mainStreamName) hierarchy.transfer_streams()