示例#1
0
 def test_rename_legacy_file_to_new(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file('slug1', legacy=True)
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     # Rename the file with the new convention of placing the UUID
     # after the slug instead of before.
     f2 = f1.replace('0000000000000001-slug1',
                     'slug1-0000000000000001')
     self._run_git('mv', f1, f2)
     self._git_commit('rename note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'2.0.0': [f2],
          '2.0.0-1': [],
          },
         results,
     )
示例#2
0
def list_cmd(args):
    "List notes files based on query arguments"
    LOG.debug('starting list')
    reporoot = args.reporoot.rstrip('/') + '/'
    notesdir = utils.get_notes_dir(args)
    collapse = args.collapse_pre_releases
    notes = scanner.get_notes_by_version(
        reporoot,
        notesdir,
        args.branch,
        collapse_pre_releases=collapse,
        earliest_version=args.earliest_version,
    )
    if args.version:
        versions = args.version
    else:
        versions = notes.keys()
    for version in versions:
        notefiles = notes[version]
        print(version)
        for n, sha in notefiles:
            if n.startswith(reporoot):
                n = n[len(reporoot):]
            print('\t%s (%s)' % (n, sha))
    return
示例#3
0
 def test_2(self):
     # Create changes on the branch before the tag into which it is
     # actually merged.
     self._add_other_file('ignore-0.txt')
     self._run_git('checkout', '-b', 'test_merge_commit')
     n1 = self._add_notes_file()
     self._run_git('checkout', 'master')
     n2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     self._add_other_file('ignore-1.txt')
     self._run_git('merge', '--no-ff', 'test_merge_commit')
     self._add_other_file('ignore-2.txt')
     self._run_git('tag', '-s', '-m', 'second tag', '2.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'1.0.0': [n2],
          '2.0.0': [n1]},
         results,
     )
     self.assertEqual(
         ['2.0.0', '1.0.0'],
         list(raw_results.keys()),
     )
示例#4
0
 def test_2(self):
     # Create changes on the branch before the tag into which it is
     # actually merged.
     self._add_other_file('ignore-0.txt')
     self._run_git('checkout', '-b', 'test_merge_commit')
     n1 = self._add_notes_file()
     self._run_git('checkout', 'master')
     n2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     self._add_other_file('ignore-1.txt')
     self._run_git('merge', '--no-ff', 'test_merge_commit')
     self._add_other_file('ignore-2.txt')
     self._run_git('tag', '-s', '-m', 'second tag', '2.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0': [n2],
             '2.0.0': [n1]
         },
         results,
     )
     self.assertEqual(
         ['2.0.0', '1.0.0'],
         list(raw_results.keys()),
     )
示例#5
0
 def test_4(self):
     # Create changes on the branch before the tag into which it is
     # actually merged, with another tag in between the time of the
     # commit and the time of the merge. This should reflect the
     # order of events described in bug #1522153.
     self._add_other_file('ignore-0.txt')
     self._run_git('checkout', '-b', 'test_merge_commit')
     n1 = self._add_notes_file()
     self._run_git('checkout', 'master')
     n2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     self._add_other_file('ignore-1.txt')
     n3 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'second tag', '1.1.0')
     self._run_git('merge', '--no-ff', 'test_merge_commit')
     self._add_other_file('ignore-2.txt')
     self._run_git('tag', '-s', '-m', 'third tag', '2.0.0')
     self._add_other_file('ignore-3.txt')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0': [n2],
             '1.1.0': [n3],
             '2.0.0': [n1]
         },
         results,
     )
     self.assertEqual(
         ['2.0.0', '1.1.0', '1.0.0'],
         list(raw_results.keys()),
     )
示例#6
0
def report_cmd(args):
    "Generates a release notes report"
    reporoot = args.reporoot.rstrip('/') + '/'
    notesdir = utils.get_notes_dir(args)
    collapse = args.collapse_pre_releases
    notes = scanner.get_notes_by_version(
        reporoot, notesdir, args.branch,
        collapse_pre_releases=collapse,
        earliest_version=args.earliest_version,
    )
    if args.version:
        versions = args.version
    else:
        versions = notes.keys()
    text = formatter.format_report(
        reporoot,
        notes,
        versions,
        title='Release Notes',
    )
    if args.output:
        with open(args.output, 'w') as f:
            f.write(text)
    else:
        print(text)
    return
示例#7
0
 def test_files_stable_from_master(self):
     self._run_git('checkout', '2.0.0')
     self._run_git('checkout', '-b', 'stable/2')
     f21 = self._add_notes_file('slug21')
     self._run_git('checkout', 'master')
     log_text = self._run_git('log', '--pretty=%x00%H %d', '--name-only',
                              'stable/2')
     self.addDetail('git log', text_content(log_text))
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
         'stable/2',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {
             '1.0.0': [self.f1],
             '2.0.0': [self.f2],
             '2.0.0-1': [f21],
         },
         results,
     )
示例#8
0
 def test_non_python_no_tags(self):
     filename = self._add_notes_file()
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {'0.0.0': [filename]},
         results,
     )
示例#9
0
 def test_note_commit_tagged(self):
     filename = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {'1.0.0': [filename]},
         results,
     )
示例#10
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        def info(msg):
            app.info('[reno] %s' % (msg,))

        title = ' '.join(self.content)
        branch = self.options.get('branch')
        reporoot_opt = self.options.get('reporoot', '.')
        reporoot = os.path.abspath(reporoot_opt)
        relnotessubdir = self.options.get('relnotessubdir',
                                          defaults.RELEASE_NOTES_SUBDIR)
        notessubdir = self.options.get('notesdir', defaults.NOTES_SUBDIR)
        version_opt = self.options.get('version')
        # FIXME(dhellmann): Force this flag True for now and figure
        # out how Sphinx passes a "false" flag later.
        collapse = True  # 'collapse-pre-releases' in self.options
        earliest_version = self.options.get('earliest-version')

        notesdir = os.path.join(relnotessubdir, notessubdir)
        info('scanning %s for %s release notes' %
             (os.path.join(reporoot, notesdir), branch or 'current branch'))

        notes = scanner.get_notes_by_version(
            reporoot, notesdir, branch,
            collapse_pre_releases=collapse,
            earliest_version=earliest_version,
        )
        if version_opt is not None:
            versions = [
                v.strip()
                for v in version_opt.split(',')
            ]
        else:
            versions = notes.keys()
        text = formatter.format_report(
            reporoot,
            notes,
            versions,
            title=title,
        )
        source_name = '<' + __name__ + '>'
        result = ViewList()
        for line in text.splitlines():
            result.append(line, source_name)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
示例#11
0
 def test_non_python_no_tags(self):
     filename = self._add_notes_file()
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'0.0.0': [filename]},
         results,
     )
示例#12
0
 def test_multiple_notes_within_tag(self):
     self._make_python_package()
     f1 = self._add_notes_file(commit=False)
     f2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {'1.0.0': [f1, f2]},
         results,
     )
示例#13
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        def info(msg):
            app.info('[reno] %s' % (msg, ))

        title = ' '.join(self.content)
        branch = self.options.get('branch')
        reporoot_opt = self.options.get('reporoot', '.')
        reporoot = os.path.abspath(reporoot_opt)
        relnotessubdir = self.options.get('relnotessubdir',
                                          defaults.RELEASE_NOTES_SUBDIR)
        notessubdir = self.options.get('notesdir', defaults.NOTES_SUBDIR)
        version_opt = self.options.get('version')
        # FIXME(dhellmann): Force this flag True for now and figure
        # out how Sphinx passes a "false" flag later.
        collapse = True  # 'collapse-pre-releases' in self.options
        earliest_version = self.options.get('earliest-version')

        notesdir = os.path.join(relnotessubdir, notessubdir)
        info('scanning %s for %s release notes' %
             (os.path.join(reporoot, notesdir), branch or 'current branch'))

        notes = scanner.get_notes_by_version(
            reporoot,
            notesdir,
            branch,
            collapse_pre_releases=collapse,
            earliest_version=earliest_version,
        )
        if version_opt is not None:
            versions = [v.strip() for v in version_opt.split(',')]
        else:
            versions = notes.keys()
        text = formatter.format_report(
            reporoot,
            notes,
            versions,
            title=title,
        )
        source_name = '<' + __name__ + '>'
        result = ViewList()
        for line in text.splitlines():
            result.append(line, source_name)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
示例#14
0
 def test_note_commit_tagged(self):
     filename = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'1.0.0': [filename]},
         results,
     )
示例#15
0
 def test_release_candidate(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0.0rc1')
     f1 = self._add_notes_file('slug1')
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0.0rc2')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0.0rc2': [f1],
         },
         results,
     )
示例#16
0
 def test_multiple_notes_within_tag(self):
     self._make_python_package()
     f1 = self._add_notes_file(commit=False)
     f2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'1.0.0': [f1, f2]},
         results,
     )
示例#17
0
文件: lister.py 项目: dhellmann/reno
def list_cmd(args):
    "List notes files based on query arguments"
    reporoot = args.reporoot.rstrip("/") + "/"
    notesdir = utils.get_notes_dir(args)
    notes = scanner.get_notes_by_version(reporoot, notesdir, args.branch)
    if args.version:
        versions = args.version
    else:
        versions = notes.keys()
    for version in versions:
        notefiles = notes[version]
        print(version)
        for n, sha in notefiles:
            if n.startswith(reporoot):
                n = n[len(reporoot) :]
            print("\t%s (%s)" % (n, sha))
    return
示例#18
0
 def test_files_current_branch(self):
     self._run_git('checkout', '2.0.0')
     self._run_git('checkout', '-b', 'stable/2')
     f21 = self._add_notes_file('slug21')
     log_text = self._run_git('log')
     self.addDetail('git log', text_content(log_text))
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0': [self.f1],
             '2.0.0': [self.f2],
             '2.0.0-1': [f21],
         },
         results,
     )
示例#19
0
 def test_delete_file(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file('slug1')
     f2 = self._add_notes_file('slug2')
     self._run_git('rm', f1)
     self._git_commit('remove note file')
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '2.0.0': [f2],
         },
         results,
     )
示例#20
0
 def test_rename_file_sort_earlier(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file('slug1')
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     f2 = f1.replace('slug1', 'slug0')
     self._run_git('mv', f1, f2)
     self._git_commit('rename note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '2.0.0': [f2],
         },
         results,
     )
示例#21
0
 def test_edit_file(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     with open(os.path.join(self.reporoot, f1), 'w') as f:
         f.write('---\npreamble: new contents for file')
     self._git_commit('edit note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '2.0.0': [f1],
         },
         results,
     )
示例#22
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        def info(msg):
            app.info('[reno] %s' % (msg,))

        title = ' '.join(self.content)
        branch = self.options.get('branch')
        reporoot_opt = self.options.get('reporoot', '.')
        reporoot = os.path.abspath(reporoot_opt)
        relnotessubdir = self.options.get('relnotessubdir',
                                          defaults.RELEASE_NOTES_SUBDIR)
        notessubdir = self.options.get('notesdir', defaults.NOTES_SUBDIR)
        version_opt = self.options.get('version')

        notesdir = os.path.join(relnotessubdir, notessubdir)
        info('scanning %s for %s release notes' %
             (os.path.join(reporoot, notesdir), branch or 'current branch'))

        notes = scanner.get_notes_by_version(reporoot, notesdir, branch)
        if version_opt is not None:
            versions = [
                v.strip()
                for v in version_opt.split(',')
            ]
        else:
            versions = notes.keys()
        text = formatter.format_report(
            reporoot,
            notes,
            versions,
            title=title,
        )
        source_name = '<' + __name__ + '>'
        result = ViewList()
        for line in text.splitlines():
            result.append(line, source_name)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
示例#23
0
 def test_edit_file(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     with open(os.path.join(self.reporoot, f1), 'w') as f:
         f.write('---\npreamble: new contents for file')
     self._git_commit('edit note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'2.0.0': [f1],
          },
         results,
     )
示例#24
0
 def test_legacy_file(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file('slug1', legacy=True)
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     f2 = f1.replace('slug1', 'slug2')
     self._run_git('mv', f1, f2)
     self._git_commit('rename note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     self.assertEqual(
         {'2.0.0': [f2],
          },
         results,
     )
示例#25
0
 def test_limit_by_earliest_version(self):
     self._make_python_package()
     self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'middle tag', '2.0.0')
     f3 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'last tag', '3.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
         earliest_version='2.0.0',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '2.0.0': [f2],
             '3.0.0': [f3],
         },
         results,
     )
示例#26
0
 def test_rename_legacy_file_to_new(self):
     self._make_python_package()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     f1 = self._add_notes_file('slug1', legacy=True)
     self._run_git('tag', '-s', '-m', 'first tag', '2.0.0')
     # Rename the file with the new convention of placing the UUID
     # after the slug instead of before.
     f2 = f1.replace('0000000000000001-slug1', 'slug1-0000000000000001')
     self._run_git('mv', f1, f2)
     self._git_commit('rename note file')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '2.0.0': [f2],
         },
         results,
     )
示例#27
0
def build_cache_db(reporoot, notesdir, branch, collapse_pre_releases,
                   versions_to_include, earliest_version):
    notes = scanner.get_notes_by_version(
        reporoot,
        notesdir,
        branch,
        collapse_pre_releases=collapse_pre_releases,
        earliest_version=earliest_version,
    )

    # Default to including all versions returned by the scanner.
    if not versions_to_include:
        versions_to_include = list(notes.keys())

    # Build a cache data structure including the file contents as well
    # as the basic data returned by the scanner.
    file_contents = {}
    for version in versions_to_include:
        for filename, sha in notes[version]:
            body = scanner.get_file_at_commit(
                reporoot,
                filename,
                sha,
            )
            # We want to save the contents of the file, which is YAML,
            # inside another YAML file. That looks terribly ugly with
            # all of the escapes needed to format it properly as
            # embedded YAML, so parse the input and convert it to a
            # data structure that can be serialized cleanly.
            y = yaml.safe_load(body)
            file_contents[filename] = y

    cache = {
        'notes': [{
            'version': k,
            'files': v
        } for k, v in notes.items()],
        'file-contents': file_contents,
    }
    return cache
示例#28
0
 def test_collapse_without_full_release(self):
     self._make_python_package()
     f1 = self._add_notes_file('slug1')
     self._run_git('tag', '-s', '-m', 'alpha tag', '1.0.0.0a1')
     f2 = self._add_notes_file('slug2')
     self._run_git('tag', '-s', '-m', 'beta tag', '1.0.0.0b1')
     f3 = self._add_notes_file('slug3')
     self._run_git('tag', '-s', '-m', 'release candidate tag', '1.0.0.0rc1')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
         collapse_pre_releases=True,
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0.0a1': [f1],
             '1.0.0.0b1': [f2],
             '1.0.0.0rc1': [f3],
         },
         results,
     )
示例#29
0
def build_cache_db(reporoot, notesdir, branch, collapse_pre_releases,
                   versions_to_include, earliest_version):
    notes = scanner.get_notes_by_version(
        reporoot, notesdir, branch,
        collapse_pre_releases=collapse_pre_releases,
        earliest_version=earliest_version,
    )

    # Default to including all versions returned by the scanner.
    if not versions_to_include:
        versions_to_include = list(notes.keys())

    # Build a cache data structure including the file contents as well
    # as the basic data returned by the scanner.
    file_contents = {}
    for version in versions_to_include:
        for filename, sha in notes[version]:
            body = scanner.get_file_at_commit(
                reporoot,
                filename,
                sha,
            )
            # We want to save the contents of the file, which is YAML,
            # inside another YAML file. That looks terribly ugly with
            # all of the escapes needed to format it properly as
            # embedded YAML, so parse the input and convert it to a
            # data structure that can be serialized cleanly.
            y = yaml.safe_load(body)
            file_contents[filename] = y

    cache = {
        'notes': [
            {'version': k, 'files': v}
            for k, v in notes.items()
        ],
        'file-contents': file_contents,
    }
    return cache
示例#30
0
 def test_collapse(self):
     files = []
     self._make_python_package()
     files.append(self._add_notes_file('slug1'))
     self._run_git('tag', '-s', '-m', 'alpha tag', '1.0.0.0a1')
     files.append(self._add_notes_file('slug2'))
     self._run_git('tag', '-s', '-m', 'beta tag', '1.0.0.0b1')
     files.append(self._add_notes_file('slug3'))
     self._run_git('tag', '-s', '-m', 'release candidate tag', '1.0.0.0rc1')
     files.append(self._add_notes_file('slug4'))
     self._run_git('tag', '-s', '-m', 'full release tag', '1.0.0')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
         collapse_pre_releases=True,
     )
     results = {k: [f for (f, n) in v] for (k, v) in raw_results.items()}
     self.assertEqual(
         {
             '1.0.0': files,
         },
         results,
     )
示例#31
0
def list_cmd(args):
    "List notes files based on query arguments"
    LOG.debug('starting list')
    reporoot = args.reporoot.rstrip('/') + '/'
    notesdir = utils.get_notes_dir(args)
    collapse = args.collapse_pre_releases
    notes = scanner.get_notes_by_version(
        reporoot, notesdir, args.branch,
        collapse_pre_releases=collapse,
        earliest_version=args.earliest_version,
    )
    if args.version:
        versions = args.version
    else:
        versions = notes.keys()
    for version in versions:
        notefiles = notes[version]
        print(version)
        for n, sha in notefiles:
            if n.startswith(reporoot):
                n = n[len(reporoot):]
            print('\t%s (%s)' % (n, sha))
    return
示例#32
0
 def test_3(self):
     # Create changes on the branch before the tag into which it is
     # actually merged, with another tag in between the time of the
     # commit and the time of the merge. This should reflect the
     # order of events described in bug #1522153.
     self._add_other_file('ignore-0.txt')
     self._run_git('checkout', '-b', 'test_merge_commit')
     n1 = self._add_notes_file()
     self._run_git('checkout', 'master')
     n2 = self._add_notes_file()
     self._run_git('tag', '-s', '-m', 'first tag', '1.0.0')
     self._add_other_file('ignore-1.txt')
     self._run_git('tag', '-s', '-m', 'second tag', '1.1.0')
     self._run_git('merge', '--no-ff', 'test_merge_commit')
     self._add_other_file('ignore-2.txt')
     self._run_git('tag', '-s', '-m', 'third tag', '2.0.0')
     self._add_other_file('ignore-3.txt')
     raw_results = scanner.get_notes_by_version(
         self.reporoot,
         'releasenotes/notes',
     )
     results = {
         k: [f for (f, n) in v]
         for (k, v) in raw_results.items()
     }
     # Since the 1.1.0 tag has no notes files, it does not appear
     # in the output. It's only there to trigger the bug as it was
     # originally reported.
     self.assertEqual(
         {'1.0.0': [n2],
          '2.0.0': [n1]},
         results,
     )
     self.assertEqual(
         ['2.0.0', '1.0.0'],
         list(raw_results.keys()),
     )
示例#33
0
    def _load_data(self):
        cache_file_exists = os.path.exists(self._cache_filename)

        if self._ignore_cache and cache_file_exists:
            LOG.debug('ignoring cache file %s', self._cache_filename)

        if (not self._ignore_cache) and cache_file_exists:
            with open(self._cache_filename, 'r') as f:
                self._cache = yaml.safe_load(f.read())
                # Save the cached scanner output to the same attribute
                # it would be in if we had loaded it "live". This
                # simplifies some of the logic in the other methods.
                self._scanner_output = {
                    n['version']: n['files']
                    for n in self._cache['notes']
                }
        else:
            self._scanner_output = scanner.get_notes_by_version(
                reporoot=self._reporoot,
                notesdir=self._notesdir,
                branch=self._branch,
                collapse_pre_releases=self._collapse_pre_releases,
                earliest_version=self._earliest_version,
            )
示例#34
0
def generate_release_notes(library, library_path,
                           start_revision, end_revision,
                           show_dates, skip_requirement_merges,
                           is_stable, series,
                           email, email_from,
                           email_to, email_reply_to, email_tags,
                           include_pypi_link,
                           changes_only,
                           first_release,
                           ):
    """Return the text of the release notes.

    :param library: The name of the library.
    :param library_path: Path to the library repository on disk.
    :param start_revision: First reference for finding change log.
    :param end_revision: Final reference for finding change log.
    :param show_dates: Boolean indicating whether or not to show dates
        in the output.
    :param skip_requirement_merges: Boolean indicating whether to
        skip merge commits for requirements changes.
    :param is_stable: Boolean indicating whether this is a stable
        series or not.
    :param series: String holding the name of the series.
    :param email: Boolean indicating whether the output format should
        be an email message.
    :param email_from: String containing the sender email address.
    :param email_to: String containing the email recipient.
    :param email_reply_to: String containing the email reply-to address.
    :param email_tags: String containing the email header topic tags to add.
    :param include_pypi_link: Boolean indicating whether or not to
        include an automatically generated link to the PyPI package
        page.
    :param changes_only: Boolean indicating whether to limit output to
        the list of changes, without any extra data.
    :param first_release: Boolean indicating whether this is the first
        release of the project

    """

    # Do not mention the series in independent model since there is none
    if series == 'independent':
        series = ''

    if not os.path.isfile(os.path.join(library_path, "setup.py")):
        raise RuntimeError("No 'setup.py' file found in %s\n" % library_path)

    if not email_from:
        raise RuntimeError('No email-from specified')

    # Get the python library/program description...
    cmd = [sys.executable, 'setup.py', '--description']
    stdout, stderr = run_cmd(cmd, cwd=library_path)
    description = stdout.strip()

    # Get the python library/program name
    cmd = [sys.executable, 'setup.py', '--name']
    stdout, stderr = run_cmd(cmd, cwd=library_path)
    library_name = stdout.strip()

    # Get the commits that are in the desired range...
    git_range = "%s..%s" % (start_revision, end_revision)
    if show_dates:
        format = "--format=%h %ci %s"
    else:
        format = "--oneline"
    cmd = ["git", "log", "--no-color", format, "--no-merges", git_range]
    stdout, stderr = run_cmd(cmd, cwd=library_path)
    changes = []
    for commit_line in stdout.splitlines():
        commit_line = commit_line.strip()
        if not commit_line or is_skippable_commit(skip_requirement_merges,
                                                  commit_line):
            continue
        else:
            changes.append(commit_line)

    # Filter out any requirement file changes...
    requirement_changes = []
    requirement_files = list(glob.glob(os.path.join(library_path,
                                                    '*requirements*.txt')))
    if requirement_files:
        cmd = ['git', 'diff', '-U0', '--no-color', git_range]
        cmd.extend(requirement_files)
        stdout, stderr = run_cmd(cmd, cwd=library_path)
        requirement_changes = [line.strip()
                               for line in stdout.splitlines() if line.strip()]

    # Get statistics about the range given...
    cmd = ['git', 'diff', '--stat', '--no-color', git_range]
    stdout, stderr = run_cmd(cmd, cwd=library_path)
    diff_stats = []
    for line in stdout.splitlines():
        line = line.strip()
        if not line or line.find("tests") != -1 or line.startswith("doc"):
            continue
        diff_stats.append(line)

    # Extract + valdiate needed sections from readme...
    readme_sections = parse_readme(library_path)
    change_header = ["Changes in %s %s" % (library_name, git_range)]
    change_header.append("-" * len(change_header[0]))

    # Look for reno notes for this version.
    branch = None
    if is_stable and series:
        branch = 'origin/stable/%s' % series
    scanner_output = scanner.get_notes_by_version(
        reporoot=library_path,
        notesdir='%s/%s' % (reno_defaults.RELEASE_NOTES_SUBDIR,
                            reno_defaults.NOTES_SUBDIR),
        branch=branch,
    )
    if end_revision in scanner_output:
        rst_notes = formatter.format_report(
            reporoot=library_path,
            scanner_output=scanner_output,
            versions_to_include=[end_revision],
        )
        reno_notes = rst2txt.convert(rst_notes)
    else:
        reno_notes = ''

    params = dict(readme_sections)
    params.update({
        'project': library_name,
        'description': description,
        'end_rev': end_revision,
        'range': git_range,
        'lib': library_path,
        'skip_requirement_merges': skip_requirement_merges,
        'changes': changes,
        'requirement_changes': requirement_changes,
        'diff_stats': diff_stats,
        'change_header': "\n".join(change_header),
        'emotion': random.choice(EMOTIONS),
        'stable_series': is_stable,
        'series': series,
        'email': email,
        'email_from': email_from,
        'email_to': email_to,
        'email_reply_to': email_reply_to,
        'email_tags': email_tags,
        'reno_notes': reno_notes,
        'first_release': first_release,
    })
    if include_pypi_link:
        params['pypi_url'] = PYPI_URL_TPL % library_name
    else:
        params['pypi_url'] = None

    response = []
    if changes_only:
        response.append(expand_template(CHANGES_ONLY_TPL, params))
    else:
        if email:
            email_header = expand_template(EMAIL_HEADER_TPL.strip(), params)
            response.append(email_header.lstrip())
        header = expand_template(HEADER_RELEASE_TPL.strip(), params)
        response.append(parawrap.fill(header))
        response.append(expand_template(CHANGE_RELEASE_TPL, params))
    return '\n'.join(response)