Exemple #1
0
def git_checkout_latest_tag(path_to_git_repository):
    if not os.path.exists(os.path.join(path_to_git_repository, ".git")):
        raise ValueError("Invalid git repository")

    git_rev_list_tags_max_count = subprocess.Popen(
        split("{git} -C {activity_path} rev-list --tags --max-count=1".format(
            git=get_executable_path("git"),
            activity_path=path_to_git_repository)),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    e_code = git_rev_list_tags_max_count.wait(50)
    if e_code != 0:
        logger.error(
            "FATAL: Could not process `rev-list --tags` for {}".format(
                path_to_git_repository))
        return 1

    git_commit_sha_of_tag, _ = decode_each(
        git_rev_list_tags_max_count.communicate())
    git_describe_tags = subprocess.Popen(
        split("{git} -C {activity_path} describe --tags {sha}".format(
            git=get_executable_path("git"),
            activity_path=path_to_git_repository,
            sha=git_commit_sha_of_tag,
        )),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    e_code = git_describe_tags.wait(50)
    if e_code != 0:
        logger.warn(
            "WARN: git describe --tags for {sha} failed for {git_repo}. "
            "Continuing to build from master...".format(
                sha=git_commit_sha_of_tag, git_repo=path_to_git_repository),
            "yellow",
        )
        return 1

    # checkout the tag
    tag, _err = decode_each(git_describe_tags.communicate())
    git_checkout_po = subprocess.Popen(
        split("{git} -C {activity_path} checkout {tag}".format(
            git=get_executable_path("git"),
            activity_path=path_to_git_repository,
            tag=tag,
        )),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    ecode = git_checkout_po.wait(500)
    if ecode != 0:
        logger.warn("WARN: checking out {} to tag {} failed. Fallback to "
                    "master.".format(path_to_git_repository, tag))
        return 1
    return 0
Exemple #2
0
    def get_git_url(self):
        """
        Returns git url  by `git config --get remote.origin.url`

        If the provided bundle inherits properties from a .xo file, then
        using git to extract commits is not sensible. A developer can tweak
        this by setting environment variable ASLOv4_ACTIVITY_XO_GITURL to
        a get the remote origin in a *.git file

        For example, if the app is called Pippy Activity, name the file
        org.laptop.Pippy.log, where org.laptop.Pippy is the bundle name.

        use
        $ git config --get remote.origin.url > org.laptop.Pippy.git

        Finally place these information in a folder, say `foobar`
        then

        $ export ASLOv4_ACTIVITY_XO_GITURL="/path/to/foobar"
        $ aslo4 --parameters-here

        This will automatically parse the information in the .git files
        inherited from git and then annotate "Source Code" button with
        the right link.
        """

        if self.is_xo:
            if not os.getenv("ASLOv4_ACTIVITY_XO_GITURL"):
                return  # bundles does not have .git directory, skip
            saas_activity_xo_giturl = os.path.join(
                os.getenv("ASLOv4_ACTIVITY_XO_GITURL"),
                "{}.git".format(self.get_bundle_id())
            )
            if not os.path.exists(saas_activity_xo_giturl):
                return
            with open(saas_activity_xo_giturl, 'r') as r:
                url = r.read()
            return url
        url_process = subprocess.Popen(
            _s('{git} -C {path} config --get remote.origin.url'.format(
                git=get_executable_path('git'),
                path=self.get_activity_dir()
            )),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        ecode = url_process.wait(timeout=5)
        if ecode != 0:
            # process did not complete successfully
            # hence no git url
            return None
        out, _ = url_process.communicate()
        url = out.decode().split('\n')
        if len(url) >= 1:
            return url[0]
Exemple #3
0
    def do_install_bundle(self, system=False):
        """
        Install the activity to a user level, if system
        keyword argument is provided to be False,
        otherwise installed to system `/usr` level
        :return:
        """
        # get optional flags
        flags = "" if system else "--user"

        # check if the current activity is already a bundle
        if self.is_xo:
            # I am a bundle. Install it by sugar-install-build provided
            # by the sugar-toolkit-gtk3 package
            sugar_install_bundle_exe = get_executable_path(
                "sugar-install-bundle")
            proc = subprocess.Popen(
                _s("{exe} {activity_xo} {flag}".format(
                    exe=sugar_install_bundle_exe,
                    activity_xo=self.activity_path,
                    flag=flags,
                )),
                cwd=self.get_activity_dir(),
                stderr=subprocess.PIPE,
                stdout=subprocess.PIPE,
            )
            exit_code = wait_for_process_completion(proc, retry=True)
            out, err = proc.communicate()
            return exit_code, out.decode(), err.decode()

        python_exe = get_executable_path(
            "python3", False) or get_executable_path("python")
        proc = subprocess.Popen(
            _s("{} setup.py install {}".format(python_exe, flags)),
            cwd=self.get_activity_dir(),
            stderr=subprocess.PIPE,
            stdout=subprocess.PIPE,
        )
        exit_code = proc.wait(timeout=120)
        out, err = proc.communicate()
        return exit_code, out.decode(), err.decode()
Exemple #4
0
def git_checkout(path_to_git_repository, branch="master"):
    if not os.path.exists(os.path.join(path_to_git_repository, '.git')):
        raise ValueError("Invalid git repository")

    git_checkout_po = subprocess.Popen(split(
        '{git} -C {activity_path} checkout {branch}'.format(
            git=get_executable_path('git'),
            activity_path=path_to_git_repository,
            branch=branch)),
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
    ecode = git_checkout_po.wait(500)

    if ecode != 0:
        logger.warn("WARN: checking out {} to {} failed.".format(
            path_to_git_repository, branch))
        return 1
    return 0
Exemple #5
0
    def create_authors_log_file(self):
        """
        Creates the log file generated by

        $ git -P log --pretty=format:"%an"

        and returns it as string

        This can be used programmatically to create log files
        from many clones. A sample code is provided below

        >>> from aslo4.generator import SaaSBuild
        >>> sb = SaaSBuild()
        >>> all_activities = sb.list_activities()
        >>>
        >>> def write_log_file(bundle_name, data):
        ...     with open(os.path.join('/foo/bar', "{}.log".format(
        ...         bundle_name))  # noqa:
        ...     ) as w:
        ...         w.write(data)  # noqa:
        >>>
        >>> for activity in all_activities:
        ...     write_log_file(
        ...         activity.get_bundle_id(),
        ...         activity.create_authors_log_file()
        ...     )
        :return: string of all the authors
        :rtype: str
        """
        author_raw = subprocess.Popen(
            _s('{git} -C {activity_path} -P log --pretty=format:"%an"'.format(
                git=get_executable_path("git"),
                activity_path=self.get_activity_dir(),
            )),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        author_raw.wait(timeout=10)
        out, _ = author_raw.communicate()
        authors = out.decode()
        return authors
    def do_generate_bundle(self,
                           override_dist_xo=False,
                           entrypoint_build_command=None,
                           build_command_chdir=False,
                           checkout_latest_tag=False):
        """
        Generates a .xo file for the activities
        by spawning a subprocess

        Some additional pro level features ;)

        The script file supports python f-strings
        Pass the parameters as named {name}, {v} to get name and version
        appropriately

        Some important format specifiers
        {name} : Activity Name
        {v} : Activity version
        {activity_dir} : the path of the Activity,
        i.e ~/FractionBounce.Activity
        {icon_path}: the path of the icon path

        Make sure you add a cd (change directory) function within the
        shell / python script
        The script is run relative to path of execution.
        To change location each time before command execution,
        pass --build-chdir
        :return: Tuple (e_code, stdout, stderr)

        """
        if self.is_xo:
            # I am already a xo. Why build me? duh
            return 0, '[xo] Already Built.', ''

        if override_dist_xo and not entrypoint_build_command:
            raise ValueError("entrypoint_build_command was not provided")

        if checkout_latest_tag and not self.is_xo:
            # checkout the latest tag on the activity build
            try:
                git_checkout_latest_tag(self.get_activity_dir())
            except Exception as e:
                cprint(
                    "WARN: git checkout to latest tag failed. E: {}".format(e),
                    "yellow")

        current_path_ = os.getcwd()
        if entrypoint_build_command and isinstance(entrypoint_build_command,
                                                   str):
            # read the shell / python script
            with open(entrypoint_build_command, 'r') as r:
                commands_to_pre_execute = r.read()

            # change dir, if necessary:
            if build_command_chdir:
                os.chdir(self.get_activity_dir())

            # execute the commands, format the f-strings before execution
            exit_code = os.system(
                commands_to_pre_execute.format(
                    name=self.get_name(),
                    v=self.get_version(),
                    activity_dir=self.get_activity_dir(),
                    icon_path=self.get_icon_path()))

            # restore the current working directory in the case directory was
            # changed
            if build_command_chdir:
                os.chdir(current_path_)

            if override_dist_xo:
                return exit_code, '', ''

        python3_exe = get_executable_path(
            'python3', False) or get_executable_path('python')
        python2_exe = get_executable_path(
            'python2', False) or get_executable_path('python')

        # check the type of activity
        if self.get_activity_type() == 'python2':
            # in the case the software to be used is sugar-activity
            # use python2 in that case.
            python_exe = python2_exe
        else:
            # use the python3 version to build all the rest of the
            # types of the activities
            python_exe = python3_exe

        proc = subprocess.Popen(_s("{} setup.py dist_xo".format(python_exe)),
                                cwd=self.get_activity_dir(),
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE)

        # wait for process to complete
        exit_code = wait_for_process_completion(proc)
        if exit_code:
            # process did not complete successfully
            return exit_code, '', ''

        # read the stdout and stderr
        out, err = proc.communicate()

        if not exit_code:
            dist_path = os.path.join(self.get_activity_dir(), 'dist')
            bundle = get_latest_bundle(dist_path)
            if bundle:
                self.set_bundle_path(bundle)

        if checkout_latest_tag and not self.is_xo:
            # restore the branch to master
            git_checkout(self.get_activity_dir())

        return exit_code, out.decode(), err.decode()