8

Git リポジトリが与えられた場合、バージョン管理された各ファイルの最終更新日の辞書を、そのファイル パスにマップされた UNIX タイムスタンプとして生成する必要があります。ファイルシステムではなく、gitに関する限り、最終更新日が必要です。

これを行うには、バージョン管理下にあるすべてのファイルのリストと、各ファイルの作成日を git に出力させたいと思います。git ls-filesorからの出力はgit ls-tree -r master、出力の各行にタイムスタンプが含まれていれば完璧です。

この出力を git から取得する方法はありますか?

より多くのコンテキストの更新:ソース管理下のすべてのファイルを反復処理し、git logそれぞれに対して実行する Python スクリプトで構成される現在の実装がありますが、うまくスケーリングできないことがわかりました。リポジトリ内のファイルが多いほど、より多くのgit log呼び出しを行う必要があります。そのため、より少ない呼び出し (理想的には 1 回のみ) で git からこの情報を収集する方法を探すようになりました。

4

4 に答える 4

0

次のスクリプトを作成して、各ファイルのパス、短いハッシュタグ、および日付を出力しました。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Author: R.F. Smith <rsmith@xs4all.nl>
# $Date: 2013-03-23 01:09:59 +0100 $
#
# To the extent possible under law, Roland Smith has waived all
# copyright and related or neighboring rights to gitdates.py. This
# work is published from the Netherlands. See
# http://creativecommons.org/publicdomain/zero/1.0/

"""For each file in a directory managed by git, get the short hash and
data of the most recent commit of that file."""

import os
import sys
import subprocess
import time
from multiprocessing import Pool

# Suppres terminal windows on MS windows.
startupinfo = None
if os.name == 'nt':
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

def filecheck(fname):
    """Start a git process to get file info. Return a string
    containing the filename, the abbreviated commit hash and the
    author date in ISO 8601 format.

    Arguments:
    fname -- Name of the file to check.
    """
    args = ['git', '--no-pager', 'log', '-1', '--format=%h|%at', fname]
    try:
        b = subprocess.check_output(args, startupinfo=startupinfo)
        data = b.decode()[:-1]
        h, t = data.split('|')
        out = (fname[2:], h, time.gmtime(float(t)))
    except (subprocess.CalledProcessError, ValueError):
        return (fname[2:], '', time.gmtime(0.0))
    return out

def main():
    """Main program."""
    # Get a list of all files
    allfiles = []
    # Get a list of excluded files.
    exargs = ['git', 'ls-files', '-i', '-o', '--exclude-standard']
    exc = subprocess.check_output(exargs).split()
    if not '.git' in os.listdir('.'):
        print('This directory is not managed by git.')
        sys.exit(0)
    for root, dirs, files in os.walk('.'):
        if '.git' in dirs:
            dirs.remove('.git')
        tmp = [os.path.join(root, f) for f in files if f not in exc]
        allfiles += tmp
    # Gather the files' data using a Pool.
    p = Pool()
    filedata = []
    for res in p.imap_unordered(filecheck, allfiles):
        filedata.append(res)
    p.close()
    # Sort the data (latest modified first) and print it
    filedata.sort(key=lambda a: a[2], reverse=True)
    dfmt = '%Y-%m-%d %H:%M:%S %Z'
    for name, tag, date in filedata:
        print('{}|{}|{}'.format(name, tag, time.strftime(dfmt, date)))


if __name__ == '__main__':
    main()
于 2013-10-03T21:07:51.443 に答える
0

私がすることは、実行git ls-filesしてそれらすべてを配列に追加し、次に実行してgit log $date_args --name-only、その出力を解析し、日付情報を辞書に追加しながら配列からそれらのファイルを削除し、配列が空になったら処理を停止することです。

于 2013-10-04T23:49:15.280 に答える