def main(): parser = make_parser() args = parser.parse_args() pathf.check_technical_area(args.area, args.module_name) module = args.module_name source = pathf.dev_module_path(module, args.area) logging.debug(source) if vcs_git.is_server_repo(source): repo = vcs_git.temp_clone(source) releases = vcs_git.list_module_releases(repo) if releases: last_release_num = releases[-1] else: print("No release has been done for " + module) # return so last_release_num can't be referenced before assignment return 1 else: raise Exception(source + " does not exist on the repository.") # Get a single log between last release and HEAD # If there is one, then changes have been made logs = list(repo.iter_commits(last_release_num + "..HEAD", max_count=1)) if logs: print("Changes have been made to " + module + " since release " + last_release_num) else: print("No changes have been made to " + module + " since most recent release " + last_release_num) shutil.rmtree(repo.working_tree_dir)
def verify_remote_repo(self): """Verifies there are no name conflicts with the remote repository. This checks whether or not there are any name conflicts between the intended module name and the modules that already exist on the remote repository. Sets the `_remote_repo_valid` boolean value to True if there are no conflicts. Raises: :class:`~dls_ade.exceptions.VerificationError`: If there is a \ name conflict with the server. """ if self._remote_repo_valid: return if vcs_git.is_server_repo(self._server_repo_path): err_message = ("The path {dir:s} already exists on gitolite," " cannot continue") raise VerificationError( err_message.format(dir=self._server_repo_path) ) self._remote_repo_valid = True
def check_remote_repo_exists(self): """Check that the server_repo_path exists on the server. Raises: :class:`AssertionError`: If the test does not pass. """ logging.debug("Checking server repo path given exists.") assert_true(vcs_git.is_server_repo(self._server_repo_path))
def push_repo(local_path): server_repo_path = local_path[len(NECESSARY_REPOS_DIR) + 1:] if not vcs_git.is_server_repo(server_repo_path): vcs_git.push_all_branches_and_tags(local_path, server_repo_path, "systest") print("Pushed to server:") else: print("This repository already exists on the server:") print(server_repo_path)
def _check_if_remote_repo_has_app(self, remote_repo_path): """Checks if the remote repository contains an app_nameApp folder. This checks whether or not there is already a folder with the name "app_nameApp" on the remote repository with the given gitolite repository path. Sets the `_remote_repo_valid` boolean value to True if there are no conflicts. Returns: bool: True if app exists, False otherwise. Raises: :class:`~dls_ade.exceptions.RemoteRepoError`: If given repo path \ does not exist on gitolite. This should never be raised. There is a bug if it is! :class:`~dls_ade.exceptions.VCSGitError`: Issue with the vcs_git \ function calls. """ if not vcs_git.is_server_repo(remote_repo_path): # This should never get raised! err_message = ("Remote repo {repo:s} does not exist. Cannot " "clone to determine if there is an app_name " "conflict with {app_name:s}") err_message = err_message.format(repo=remote_repo_path, app_name=self._app_name) raise RemoteRepoError(err_message) temp_dir = "" exists = False try: repo = vcs_git.temp_clone(remote_repo_path) temp_dir = repo.working_tree_dir if os.path.exists(os.path.join(temp_dir, self._app_name + "App")): exists = True finally: try: if temp_dir: shutil.rmtree(temp_dir) except OSError: pass return exists
def verify_remote_repo(self): """Verifies there are no name conflicts with the remote repository. This checks whether or not there are any name conflicts between the intended module and app names, and the modules that already exist on the remote repository. Sets the `_remote_repo_valid` boolean value to True if there are no conflicts. This method will fail (raise a VerificationError) if: - There is no remote repository to clone from - There is an app_name conflict with one of the remote paths Raises: :class:`~dls_ade.exceptions.VerificationError`: If there is an \ issue with the remote repository. :class:`~dls_ade.exceptions.RemoteRepoError`: If the given server \ path does not exist. This should never be raised. There is a bug if it is! """ if self._remote_repo_valid: return if not vcs_git.is_server_repo(self._server_repo_path): err_message = ("The path {path:s} does not exist on gitolite, so " "cannot clone from it") err_message = err_message.format(path=self._server_repo_path) raise VerificationError(err_message) conflicting_path = self._check_if_remote_repo_has_app( self._server_repo_path ) if conflicting_path: err_message = ("The repository {path:s} has an app that conflicts " "with app name: {app_name:s}") err_message = err_message.format( path=self._server_repo_path, app_name=self._app_name ) raise VerificationError(err_message) self._remote_repo_valid = True
def set_server_repo_to_default(self): """Sets the given server repository to a default state. Note: If used on an existing server repository, all commit history will be overwritten. Raises: :class:`.SettingsError`: If default given but no server repo. :class:`dls_ade.exceptions.VCSGitError`: From \ :mod:`~dls_ade.vcs_git` functions. """ if not self._default_server_repo_path: return if not self._server_repo_path: raise SettingsError("If 'default_server_repo_path is set, then " "'server_repo_path' must also be set.") logging.debug("Setting server repo to default.") logging.debug("'Default' server repo path: " + self._default_server_repo_path) temp_repo = vcs_git.temp_clone(self._default_server_repo_path) vcs_git.delete_remote(temp_repo.working_tree_dir, "origin") if vcs_git.is_server_repo(self._server_repo_path): temp_repo.create_remote( "origin", os.path.join(vcs_git.GIT_SSH_ROOT, self._server_repo_path) ) temp_repo.git.push("origin", temp_repo.active_branch, "-f") else: vcs_git.add_new_remote_and_push(self._server_repo_path, temp_repo.working_tree_dir)
def get_module_creator_ioc(module_name, fullname=False): """Returns a :class:`ModuleCreatorIOC` subclass object. Returns an object of a subclass of :class:`ModuleCreatorIOC`, depending on the arguments given. IOC module name format: New-Style module (preferred): Format: "BL02I-VA-IOC-03" "<beamline>-<technical_area>-IOC-<ioc_number>" Alternative: "BL02I/VA/03", with fullname = True "<beamline>/<technical_area>/<ioc_number>", fullname = True If the alternative is used, if the IOC number is omitted (eg. <beamline>/<technical_area>) it defaults to "01" Old-Style module (deprecated, except for BL modules): Format: "BL02I/VA/03", with fullname = False (or omitted) "<beamline>/<technical_area>/<ioc_number>" Args: module_name: The name of the module. fullname: Create new-style module from old-style input. If True and module_name given in old-style format, then a new-style module is created. Returns: ModuleCreatorIOC: :class:`ModuleCreatorIOC` subclass object Raises: ParsingError: If the module cannot be split by '-' or '/'. """ area = "ioc" dash_separated, cols = split_ioc_module_name(module_name) domain = cols[0] technical_area = cols[1] if technical_area == "BL": if dash_separated: app_name = module_name module_path = domain + "/" + app_name else: app_name = domain module_path = domain + "/" + technical_area return mc.ModuleCreatorWithApps(module_path, area, mt.ModuleTemplateIOCBL, app_name=app_name) module_template_cls = mt.ModuleTemplateIOC if dash_separated: app_name = module_name module_path = domain + "/" + app_name return mc.ModuleCreatorWithApps(module_path, area, module_template_cls, app_name=app_name) if len(cols) == 3 and cols[2]: ioc_number = cols[2] else: ioc_number = "01" app_name = "-".join([domain, technical_area, "IOC", ioc_number]) if fullname: module_path = domain + "/" + app_name return mc.ModuleCreatorWithApps(module_path, area, module_template_cls, app_name=app_name) else: # This part is here to retain compatibility with "old-style" modules, # in which a single repo (or module) named "domain/technical_area" # contains multiple domain-technical_area-IOC-xxApp's. This code is # included in here to retain compatibility with the older svn scripts. # The naming is ambiguous, however. I will continue to use the name # 'module' to refer to the repo, but be aware that start_new_module and # module_creator don't have to actually create new modules (repos) # on the server in this instance. module_path = domain + "/" + technical_area server_repo_path = pathf.dev_module_path(module_path, area) if vcs_git.is_server_repo(server_repo_path): # Adding new App to old style "domain/tech_area" module that # already exists on the remote server. return mc.ModuleCreatorAddAppToModule(module_path, area, module_template_cls, app_name=app_name) else: # Otherwise, the behaviour is exactly the same as that given # by the ordinary IOC class as module_path is the only thing # that is different return mc.ModuleCreatorWithApps(module_path, area, module_template_cls, app_name=app_name)
def main(): parser = make_parser() args = parser.parse_args() raw = set_raw_argument(args.raw) pathf.check_technical_area(args.area, args.module_name) check_parsed_args_compatible(args.releases, args.earlier_release, args.later_release, parser) check_releases_valid(args.releases, parser) source = pathf.dev_module_path(args.module_name, args.area) if vcs_git.is_server_repo(source): repo = vcs_git.temp_clone(source) releases = vcs_git.list_module_releases(repo) logging.debug(releases) else: raise Exception("Module " + args.module_name + " doesn't exist in " + source) # Set start and end releases and check they exist, set to defaults if not given start, end = set_log_range(args.module_name, args.releases, args.earlier_release, args.later_release, releases) # Create log info from log messages # log_info is a dictionary in the form {logs(list), commit_objects(dict), max_author_length(int)} log_info = get_log_messages(repo) if len(releases) > 0: if start == "": tag_start = releases[0] else: tag_start = start # Append tag info to log info from tag messages tags = get_tags_list(repo, tag_start, end, releases[-1]) log_info = get_tag_messages(tags, log_info) # Check if there are any logs, exit if not if not log_info['logs']: print("No logs for " + args.module_name + " between releases " + args.earlier_release + " and " + args.later_release) return 0 # Sort tags and commits chronologically by the UNIX time stamp in index 0 log_info['logs'] = sorted(log_info['logs'], key=itemgetter(0)) # Make list of printable log entries formatted_logs = format_log_messages(log_info, raw, args.verbose) if end == 'HEAD': print_bool = True else: print_bool = False release_marker = "(RELEASE: {})" for log in formatted_logs: if log.endswith(release_marker.format(end)): print_bool = True if print_bool: print(log) if log.endswith(release_marker.format(start)): break shutil.rmtree(repo.working_tree_dir)