Обработка расширенных команд git с помощью модуля подпроцесса python - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь извлечь и работать с данными из исторических версий файлов в git-репо.Я хотел бы иметь что-то вроде словаря, который содержит <hash>, <time of commit>, <value retrieved from contents of a file revision>, <commit message> для каждой записи.

Я подумал, что данные, которые я получаю из каждой ревизии файла, и любые вычисления, выполненные с ними, лучше всего обрабатывать с использованием python.И модуль подпроцесса оказался наиболее подходящим для интеграции моих команд git.

Ниже я покажу, как я определяю функцию getval(key, filename), которая, как я надеялся, выведет <SHA-1 hash>:<Value> на консоль, но хотелось бычтобы иметь диктовку с дополнительной информацией ... также с <time> и <commit message>.

Я помогаю управлять ионным ускорителем, где мы сохраняем «наборы настроек» - или значения, относящиеся к данной мелодии ускорителя- используя мерзавец.Из значений в этих файлах такие вещи, как заряд (Q) и масса (A).В конечном счете, я хочу получить оба значения, получить соотношение (Q / A) и отобразить список хэшей редакций файлов, отсортированных по соотношению заряда: массы иона, который мы доставили с настройками в редакции этого файла.

Пример файла (для 56Fe17 +):

# Date: 2018-12-21 01:49:16.888 PV,SELECTED,TIMESTAMP,STATUS,SEVERITY,VALUE_TYPE,VALUE,READBACK,READBACK_VALUE,DELTA,READ_ONLY REA_EXP:LINE,0,1544047322.881066957,NO_ALARM,NONE,enum,"JENSA~[UDF;AT-TPC;GPL;JENSA]",,"---",,true REA_BTS19:BEAM:OPTICSFILE,0,1541798820.065952460,NO_ALARM,NONE,string,"BTS19_test3.data",,"---",,true REA_BTS19:BEAM:A_BOOK,0,1545322510.562031883,NO_ALARM,NONE,double,"56.0",,"---",,true REA_BTS19:BEAM:Z_BOOK,0,1545322567.544226340,NO_ALARM,NONE,double,"26.0",,"---",,true REA_BTS19:BEAM:Q_BOOK,0,1545322512.701768974,NO_ALARM,NONE,double,"17.0",,"---",,true

Пока - и с помощью других здесь - я выяснилgit one-liner, который обрабатывает историю изменений заданного файла для ключа [строки] и использует sed и awk для вывода <hash>:<val associated with the key>.

Git Oneliner Я начинаю с:

git grep 'BTS19:BEAM:A_BOOK' $(git rev-list --all) -- ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp | sed 's/:/,/' | awk -F, '{print $1 ":" $8}'

Выход Oneliner

e78f73fe6f90e93d5b3ccf90975b0e540d12ce09:"56.0" 4b94745bd0a6594bb42a774c95b5fc0847ef2d82:"56.0" f2d5e263deac1d9112be791b39f4ce1b1b34e55d:"56.0" c03800de52143ddb2abfab51fcc665ff5470e363:"56.0" 4a3a564a6d87bc6ff5f3dc7fec7670aeecfe6a79:"58.0" d591941e51c4eab1237ce726a2a49448114b8f26:"58.0" a9c8f5cdf224ff4fd94514c33888796760afd792:"58.0" 2f221492beea1663216dcfb27da89343817b11fd:"58.0"

Я также начал играть с модулем Python подпроцесса,Но я изо всех сил пытаюсь понять, как обрабатывать мои более сложные команды git.Как правило, я хочу иметь возможность передавать ключ и файл .. что-то вроде getval(key, filename).

Когда моей строкой cmd было ['git', 'grep', str, '$ (git rev-list --all) ',' - ', pathspec], он вернул ошибки о том, что $ (git rev-list --all)' был неоднозначным.Думая, что он не расширяется, я добавил отдельный процесс для выполнения вложенной команды, но я не уверен, что делаю это правильно.

Мой файл Python (gitfun.py): в настоящее время я запускаю функцию из

import sys, os
import subprocess

def getval(str, pathspec, repoDir='/mnt/d/stash.projects/rea'):
    p1 = subprocess.Popen(["git", "rev-list", "--all"], stdout=subprocess.PIPE)
    output, err = p1.communicate()

    cmd = ['git', 'grep', str, output, '--', pathspec]        
    p2 = subprocess.Popen(cmd, cwd=repoDir)
    p2.wait()

cwd = '/mnt/d/stash.projects/rea'
filename = 'ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp'
os.chdir(cwd)
getval('BTS19:BEAM:A_BOOK', filename)

В настоящее время она возвращает 'file name too long', поэтому (хотя я не уверен, что это действительно слишком долго), я попытался изменить свои core.longpathsв git config значение true, однако это не имело никакого эффекта.Опять же, почему я подозреваю, что неправильно выполняю замену расширения $ (git rev-list --all).

Для этого кода, я ожидаю что-то похожее на это:

522628b8d3db01ac330240b28935933b0448649c:ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp:REA_BTS19:BEAM:A_BOOK,0,1545240215.74320185 5,NO_ALARM,NONE,double,"58.0",,"---",,true 2557c599d2dc67d80ffc5b9be3f79899e0c15a10:ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp:REA_BTS19:BEAM:A_BOOK,0,1545240215.74320185 5,NO_ALARM,NONE,double,"58.0",,"---",,true 7fc97ec2aa76f32265196c42dbcd289c49f0ad93:ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp:REA_BTS19:BEAM:A_BOOK,0,1545240215.74320185 5,NO_ALARM,NONE,double,"58.0",,"---",,true ...

Но я, в конечном счете, хочу вывод на консоль, который будет выглядеть так же, как git one-liner выше, или, что еще лучше, диктоватьЯ могу печатать на консоль или делать другие вещи.

1 Ответ

0 голосов
/ 03 января 2019

Помните, что ваша оболочка токенизирует командную строку, используя пробел.

Когда вы запускаете git rev-list --all, вы получаете вывод, подобный:

2a4be2748fad885f88163a5b9b1b438fe3cb2ece
c1a30c743eb810fbefe1dc314277931fa33842b3
b2e5c75131e94a3543e5dcf9fb641ccd553906b4
95718f7e128a8b36ca93d6589328cc5b739668b1
87a9ada188a8cd1c13e48c21f093be7027d61eca

Когда вы подставляете его в git grep команда ...

git grep 'BTS19:BEAM:A_BOOK' $(git rev-list --all) -- \
ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp

... каждая строка представляет собой отдельный аргумент .То есть, если вывод git rev-list --all был в точности таким, как я показал выше, ваша однострочная строка была бы разбита на следующие аргументы, которые для ясности я перечислил по одному в строке:

git
grep
BTS19:BEAM:A_BOOK
2a4be2748fad885f88163a5b9b1b438fe3cb2ece
c1a30c743eb810fbefe1dc314277931fa33842b3
b2e5c75131e94a3543e5dcf9fb641ccd553906b4
95718f7e128a8b36ca93d6589328cc5b739668b1
87a9ada188a8cd1c13e48c21f093be7027d61eca
--
ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp

Но вы не делаете это в своем коде Python!Вы вставляете весь вывод git rev-list --all как single аргумент.Это означает, что команда, которую вы пытаетесь выполнить, имеет фиксированное число (6) аргументов:

git
grep
BTS19:BEAM:A_BOOK
2a4be2748fad885f88163a5b9b1b438fe3cb2ece c1a30c743eb810fbefe1dc314277931fa33842b3 b2e5c75131e94a3543e5dcf9fb641ccd553906b4 95718f7e128a8b36ca93d6589328cc5b739668b1 87a9ada188a8cd1c13e48c21f093be7027d61eca
--
ReAccelerator/Snapshots/RFQ-JENSA_Setpoints.snp

Все эти ревизии объединяются в один аргумент, где «слишком длинное имя файла»ошибка приходит.Вам нужно разделить этот вывод на несколько аргументов, как это делает оболочка:

p1 = subprocess.Popen(["git", "rev-list", "--all"], stdout=subprocess.PIPE)
output, err = p1.communicate()

cmd = ['git', 'grep', str] + output.splitlines() + ['--', pathspec]        
p2 = subprocess.Popen(cmd, cwd=repoDir)
p2.wait()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...