def _prepare_build_environ(self, project, obs_work_dir): """ 准备obs build环境 :param project: obs项目 :param obs_work_dir: obs工作目录 :return: """ _process_perl_path = os.path.realpath( os.path.join(os.path.realpath(__file__), "../process_service.pl")) _service_file_path = os.path.join(obs_work_dir, project, self._package, "_service") _obs_package_path = os.path.join(obs_work_dir, project, self._package) cmd = "perl {} -f {} -p {} -m {} -w {}".format(_process_perl_path, _service_file_path, project, self._package, _obs_package_path) ret, _, _ = shell_cmd_live(cmd, verbose=True) if ret: logger.error("prepare build environ error, {}".format(ret)) return False return True
def list_packages_of_state(project, state): """ 获取project下某个状态的包列表 :param project: obs项目 :param state: 状态 :return: list<str> """ cmd = "osc results {} --csv |grep {} | awk -F';' '{{print $1}}'".format(project, state) ret, out, _ = shell_cmd_live(cmd, cap_out=True) if ret: logger.debug("list package of state error, {}".format(ret)) return [] return out
def checkout_to_commit(self, commit): """ git checkout :param commit: HEAD~{} or SHA :return: boolean """ checkout_cmd = "cd {}; git checkout {}".format(self._repo_dir, commit) ret, _, _ = shell_cmd_live(checkout_cmd) if ret: logger.warning("checkout failed, {}".format(ret)) return False return True
def list_project(project, package=""): """ 列出项目下包列表 :param project: :param package: :return: """ cmd = "osc ll {} {}".format(project, package) ret, rs, _ = shell_cmd_live(cmd, cap_out=True) if ret: logger.error("list project package error, {}".format(ret)) return None return rs
def extract_files_path_of_patch(self, patch_path): """ 获取patch内diff的文件路径 :param patch_path: patch完整路径 :return: list<string> """ extract_file_cmd = "cd {}; git apply --numstat {}".format( self._repo_dir, patch_path) ret, out, _ = shell_cmd_live(extract_file_cmd, cap_out=True) if ret: logger.error("extract diff files of patch failed, {}".format(ret)) return [] return [line.split()[-1] for line in out]
def commit_id_of_reverse_head_index(self, index=0): """ 对应的commit hash :param index: HEAD~index :return: hash string """ get_commit_cmd = "cd {}; git rev-parse {}".format( self._repo_dir, "HEAD~{}".format(index)) ret, out, _ = shell_cmd_live(get_commit_cmd, cap_out=True) if ret: logger.error("get commit id of index failed, {}".format(ret)) return None return out[0]
def diff_files_between_commits(self, base, head): """ 获取2次提交的差别的文件名列表 :param base: 被比较的版本 :param head: 比较的版本 :return: list<string> """ diff_files_cmd = "cd {}; git diff --name-only --diff-filter=ACM {} {}".format( self._repo_dir, base, head) ret, out, _ = shell_cmd_live(diff_files_cmd, cap_out=True) if ret: logger.error("get diff files of commits failed, {}".format(ret)) return [] return out
def build_history(project, package, repo, arch): """ 构建历史 :param project: :param package: :param repo: :param arch: :return: """ cmd = "osc api /build/{}/{}/{}/{}/_history".format(project, repo, arch, package) ret, out, _ = shell_cmd_live(cmd, cap_out=True) if ret: logger.debug("list build history of package error, {}".format(ret)) return "" return "\n".join(out)
def apply_patch(self, patch_path, leading=0): """ 打补丁 :param patch_path: patch完整路径 :param leading: Remove <n> leading path components :return: boolean """ apply_patch_cmd = "cd {}; git apply -p{} {}".format( self._repo_dir, leading, patch_path) ret, _, _ = shell_cmd_live(apply_patch_cmd) if ret: #logger.error("apply patch failed, {}".format(ret)) return False return True
def check_install_rpm(self, branch_name, arch, install_root): """ 检查生成的rpm是否可以安装 :param branch_name: 分支名 :param arch: cpu架构 :param install_root: 安装根路径 :return: """ logger.info("*** start check install start ***") # 1. prepare install root directory _ = not os.path.exists(install_root) and os.mkdir(install_root) logger.info("create install root directory: {}".format(install_root)) repo_name_prefix = "check_install" # 2. prepare repo repo_source = OBSRepoSource("http://119.3.219.20:82") # obs 实时构建repo地址 repo_config = repo_source.generate_repo_info(branch_name, arch, "check_install") logger.info("repo source config:\n{}".format(repo_config)) # write to /etc/yum.repos.d with open("obs_realtime.repo", "w+") as f: f.write(repo_config) # 3. dnf install using repo name start with "check_install" names = [] packages = [] for name, package in self._rpm_package.iter_all_rpm(): # ignore debuginfo rpm if "debuginfo" in name or "debugsource" in name: logger.debug("ignore debug rpm: {}".format(name)) continue names.append(name) packages.append(package) logger.info("install rpms: {}".format(names)) if packages: check_install_cmd = "sudo dnf install -y --installroot={} --setopt=reposdir=. {}".format( install_root, " ".join(packages)) ret, _, err = shell_cmd_live(check_install_cmd, verbose=True) if ret: logger.error("install rpms error, {}, {}".format(ret, err)) else: logger.info("install rpm success")
def init_repository(cls, sub_dir, work_dir=None): """ 初始化git仓库 :param sub_dir: 仓库子目录 :param work_dir: 仓库根目录 :return: GitProxy() or None """ repo_dir = os.path.join(work_dir, sub_dir) if work_dir else sub_dir init_cmd = "git init {}".format(repo_dir) ret, _, _ = shell_cmd_live(init_cmd) if ret: logger.warning("init repository failed, {}".format(ret)) return None return cls(repo_dir)
def apply_patch_at_dir(cls, patch_dir, patch_path, leading=0): """ 到指定目录下打补丁 :param patch_path: patch完整路径 :param patch_dir: patch使用路径 :param leading: Remove <n> leading path components :return: boolean """ #apply_patch_cmd = "cd {}; patch -l -t -p{} < {}".format(patch_dir, leading, patch_path) apply_patch_cmd = "cd {}; git apply --ignore-whitespace -p{} {}".format( patch_dir, leading, patch_path) ret, _, _ = shell_cmd_live(apply_patch_cmd) if ret: #logger.error("apply patch failed, {}".format(ret)) return False return True
def get_content_of_file_with_commit(self, file_path, commit="HEAD~0"): """ 获取单个commit文件内容 :param commit: HEAD~{} or SHA :param file_path: 文件完整路径 :return: StringIO """ get_content_cmd = "cd {}; git show {}:{}".format( self._repo_dir, commit, file_path) ret, out, _ = shell_cmd_live(get_content_cmd, cap_out=True) if ret: logger.warning("get file content of commit failed, {}".format(ret)) return None f = StringIO() f.write("\n".join(out)) f.seek(0) return f
def fetch_commit_with_depth(self, depth): """ git fetch :param depth: fetch 提交深度,0表示全部提交 :return: boolean """ if 0 == depth: fetch_cmd = "cd {}; git fetch --unshallow".format(self._repo_dir) else: fetch_cmd = "cd {}; git fetch --depth {}".format( self._repo_dir, depth) ret, _, _ = shell_cmd_live(fetch_cmd) if ret: logger.error("fetch failed, {}".format(ret)) return False return True
def checkout_package(project, package): """ checkout :param project: :param package: :return: 成功返回True,失败返回False """ # pod cache _ = os.path.isdir(project) and shutil.rmtree(project) cmd = "osc co {} {}".format(project, package) logger.info("osc co {} {}".format(project, package)) ret, _, _ = shell_cmd_live(cmd, verbose=True) if ret: logger.error("checkout package error, {}".format(ret)) return False return True
def list_repos_of_arch(project, package, arch, show_exclude=False): """ 获取包的repo列表 :param project: :param package: :return: """ cmd = "osc results {} {} {} -a {}".format( "--show-exclude" if show_exclude else "", project, package, arch) ret, out, _ = shell_cmd_live(cmd, cap_out=True) if ret: logger.debug("list obs repos of arch error, {}".format(ret)) return [] rs = [] for line in out: repo, arch, state = line.split() rs.append({"repo": repo, "state": state}) return rs
def fetch_pull_request(self, url, pull_request, depth=1, progress=False): """ fetch pr :param url: 仓库地址 :param pull_request: pr编号 :param depth: 深度 :param progress: 展示进度 :return: """ fetch_cmd = "cd {}; git fetch {} --depth {} {} +refs/pull/{}/MERGE:refs/pull/{}/MERGE".format( self._repo_dir, "--progress" if progress else "", depth, url, pull_request, pull_request) ret, out, _ = shell_cmd_live(fetch_cmd, cap_out=True, cmd_verbose=False) if ret: logger.error("git fetch failed, {}".format(ret)) logger.error("{}".format(out)) return False return True
def decompress_file(self, file_path): """ 解压缩文件 :param file_path: :return: """ if self._is_compress_zip_file(file_path): decompress_cmd = "cd {}; timeout 120s unzip -o -d {} {}".format( self._work_dir, self._decompress_dir, file_path) elif self._is_compress_tar_file(file_path): decompress_cmd = "cd {}; timeout 120s tar -C {} -xavf {}".format( self._work_dir, self._decompress_dir, file_path) else: logger.warning("unsupport compress file: {}".format(file_path)) return False ret, _, _ = shell_cmd_live(decompress_cmd) if ret: logger.debug("decompress failed") return False return True
def build_package(project, package, repo, arch, debug=False): """ build :param project: :param package: :param repo: :param arch: :param debug: :return: """ package_path = "{}/{}".format(project, package) cmd = "cd {}; osc build {} {} {} --no-verify --clean --noservice".format( package_path, repo, arch, "--disable-debuginfo" if not debug else "") logger.info("osc build {} {} {} --no-verify --clean".format( repo, arch, "--disable-debuginfo" if not debug else "")) ret, _, _ = shell_cmd_live(cmd, verbose=True) if ret: logger.error("build package error, {}".format(ret)) return False return True
def get_tree_hashes(self, commit, number=0, with_merges=True): """ 获取tree对象hash值 :param commit: HEAD~{} or SHA :param number: hash numbers :return: hash string """ if 0 == number: tree_hashes_cmd = "cd {}; git log --format=%T {}".format( self._repo_dir, commit) else: tree_hashes_cmd = "cd {}; git log --format=%T -n{} {}".format( self._repo_dir, number, commit) if not with_merges: tree_hashes_cmd = "{} --no-merges".format(tree_hashes_cmd) ret, out, _ = shell_cmd_live(tree_hashes_cmd, cap_out=True) if ret: logger.error("get tree hashes failed, {}".format(ret)) return None return out