Last active
October 26, 2020 19:28
-
-
Save 5263/0f1554decb1cd329f4ee to your computer and use it in GitHub Desktop.
FreeCAD files git repo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import zip2git | |
from PySide import QtGui | |
# 1. Choose repository (directiory) | |
repodir = QtGui.QFileDialog.getExistingDirectory(QtGui.qApp.activeWindow()) | |
if repodir: | |
# ToDO: 2. List branches in a list and let the user choose one | |
# ToDo: 3. List commits in a list and let the user choose one | |
# ToDo: 4. Check if it would overwrite a file. And if the file is | |
# part of the repo. Ask the user for cofirmation | |
zip2git.checkoutandload(ref=None,repopath=repodir) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from PySide import QtGui | |
from PySide import QtCore | |
class GitRepoForm(QtGui.QDialog): | |
def __init__(self,parent=None): | |
super(GitRepoForm,self).__init__(parent) | |
layout = QtGui.QVBoxLayout(self) | |
self.setLayout(layout) | |
hsplitter = QtGui.QSplitter(self) | |
self.lv1 = QtGui.QListWidget(self) | |
self.lv1.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) | |
self.lv2 = QtGui.QTableWidget(self) | |
hsplitter.addWidget(self.lv1) | |
hsplitter.addWidget(self.lv2) | |
h1layout = QtGui.QHBoxLayout() | |
self.repopathle=QtGui.QLineEdit(u".",parent=self) | |
h1layout.addWidget(self.repopathle) | |
self.dirdialogbutton=QtGui.QPushButton('...') | |
h1layout.addWidget(self.dirdialogbutton) | |
layout.addLayout(h1layout) | |
layout.addWidget(hsplitter) | |
self.buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok\ | |
|QtGui.QDialogButtonBox.Cancel) | |
layout.addWidget(self.buttons) | |
self.buttons.accepted.connect(self.onOkButtonClicked) | |
self.buttons.rejected.connect(self.reject) | |
self.dirdialogbutton.clicked.connect(self.onDirDialogButtonClicked) | |
self.repopathle.textChanged.connect(self.updateReflist) | |
self.lv1.itemSelectionChanged.connect(self.updateCommitlist) | |
self.refs={} | |
self.updateReflist() | |
@QtCore.Slot() | |
def onDirDialogButtonClicked(self): | |
repodir = QtGui.QFileDialog.getExistingDirectory(\ | |
QtGui.qApp.activeWindow()) | |
if repodir: | |
self.repopathle.setText(repodir) | |
@QtCore.Slot() | |
def updateReflist(self): | |
def sortkey(val): | |
nohyphen=val[-36:].replace('-','') | |
return (len(val.rsplit('/',1)[-1]) == 36 and len(nohyphen) ==\ | |
32 and all(c in '0123456789abcdef' for c in nohyphen),val) | |
import dulwich #zip2git | |
import dulwich.repo | |
try: | |
repo=dulwich.repo.Repo(self.repopathle.text()) | |
self.refs=repo.get_refs() | |
self.keys=sorted(self.refs.keys(),key=sortkey) | |
self.lv1.clear() | |
self.lv1.addItems(self.keys) | |
except dulwich.repo.NotGitRepository: | |
self.lv1.clear() | |
@QtCore.Slot(int) | |
def updateCommitlist(self,index=None): | |
self.lv2.clear() | |
commits=set() | |
for listitem in self.lv1.selectedItems(): | |
refname=listitem.text() | |
if refname in self.refs: | |
commits.add(self.refs[refname]) | |
#print commits | |
import dulwich | |
import zip2git | |
repo=dulwich.repo.Repo(self.repopathle.text()) | |
walker=repo.get_walker(include=list(commits)) | |
self.lv2.clear() | |
self.lv2.setColumnCount(13) | |
self.lv2.setRowCount(0) | |
self.lv2.setHorizontalHeaderLabels(("Label",'Last Modified',\ | |
"Modified by","Comment","License","tree", "commit","UUID",\ | |
"Program Version","Created","Created by","Company","Id")) | |
for row,we in enumerate(walker): | |
c=we.commit | |
twiauthortime=QtGui.QTableWidgetItem(zip2git.git2datetime(\ | |
c.author_time,c.author_timezone).strftime('%F %T %z')) | |
twiauthor=QtGui.QTableWidgetItem(c.author) | |
twitreeid=QtGui.QTableWidgetItem(c.tree) | |
twicommitid=QtGui.QTableWidgetItem(c.id) | |
self.lv2.insertRow(row) | |
self.lv2.setItem(row, 1, twiauthortime) | |
self.lv2.setItem(row, 2, twiauthor) | |
self.lv2.setItem(row, 5, twitreeid) | |
self.lv2.setItem(row, 6, twicommitid) | |
propertiesdict=zip2git.tree2propertiesdict(c.tree,repo) | |
if propertiesdict is not None: | |
uuid=zip2git.extractuidpropertiesdict(propertiesdict) | |
twiuuid = QtGui.QTableWidgetItem(uuid) | |
self.lv2.setItem(row, 7, twiuuid) | |
for key,listindex in (('Label',0),('License',4),\ | |
('Comment',3),('Company',11),('CreationDate',9),\ | |
('CreatedBy',10),("Id",12),("ProgramVersion",8)): | |
value=propertiesdict.get(key) | |
if value: | |
tableitem=QtGui.QTableWidgetItem(value) | |
self.lv2.setItem(row, listindex, tableitem) | |
@QtCore.Slot() | |
def onOkButtonClicked(self): | |
commits=set() | |
for srange in self.lv2.selectedRanges(): | |
for rowindex in range(srange.topRow(),srange.bottomRow()+1): | |
#print rowindex | |
commits.add(self.lv2.item(rowindex,6).text()) #commitid | |
if len(commits) == 1: | |
commitid=tuple(commits)[0] | |
repopath=self.repopathle.text() | |
import zip2git | |
zipfilepath=zip2git.checkoutfile(commitid,True,repopath=repopath) | |
if zipfilepath: | |
import FreeCAD | |
doc=FreeCAD.openDocument(zipfilepath) | |
if not hasattr(FreeCAD,'_doc2git'): | |
FreeCAD._doc2git={} | |
FreeCAD._doc2git[doc]={'repopath':repopath,'parents':\ | |
[commitid]} #'branch': ? | |
if len(self.lv1.selectedItems()) == 1: | |
FreeCAD._doc2git[doc]['branch'] = self.lv1.selectedItems()\ | |
[0].text() | |
self.accept() | |
if __name__ == '__main__': | |
qApp = QtGui.qApp | |
if qApp is not None: | |
parent = QtGui.qApp.activeWindow() | |
else: | |
import sys | |
app = QtGui.QApplication(sys.argv) | |
parent = None | |
form = GitRepoForm(parent) | |
form.show() | |
# if parent is None: | |
# import sys | |
# sys.exit(qApp.exec_()) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import FreeCAD,zip2git | |
reload(zip2git) | |
doc=FreeCAD.activeDocument() | |
if doc is None: | |
raise ValueError('No Document') | |
if not doc.FileName: | |
import FreeCADGui | |
Gui.SendMsgToActiveView("SaveAs") | |
if doc.FileName: | |
#file was saved from the gui allready | |
commitid=zip2git.saveandcommit(save=False) | |
else: | |
raise ValueError('No Filename set') | |
else: | |
commitid=zip2git.saveandcommit() | |
if commitid: | |
FreeCAD.Console.PrintLog('commit id %s\n' % commitid) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#*************************************************************************** | |
#* * | |
#* Copyright (c) 2014 Sebastian Hoogen <[email protected]> * | |
#* * | |
#* This program is free software; you can redistribute it and/or modify * | |
#* it under the terms of the GNU Lesser General Public License (LGPL) * | |
#* as published by the Free Software Foundation; either version 2 of * | |
#* the License, or (at your option) any later version. * | |
#* for detail see the LICENCE text file. * | |
#* * | |
#* This program is distributed in the hope that it will be useful, * | |
#* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
#* GNU Library General Public License for more details. * | |
#* * | |
#* You should have received a copy of the GNU Library General Public * | |
#* License along with this program; if not, write to the Free Software * | |
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | |
#* USA * | |
#* * | |
#*************************************************************************** | |
__title__="FreeCAD Git resource backend" | |
import zipfile | |
import dulwich | |
import dulwich.repo | |
import dulwich.objects | |
import xml.sax | |
import xml.sax.handler | |
import xml.sax.xmlreader | |
defaultcommiter = 'unknown <>' | |
class DocumentHandler(xml.sax.handler.ContentHandler): | |
"""adaped form DlgProjectUtility.cpp (c) wmayer 2011 LGPL2+""" | |
def __init__(self): | |
self.files = [] | |
def startElement(self, name, attributes): | |
item=attributes.get("file") | |
if item != None: | |
self.files.append(str(item)) | |
def characters(self, data): | |
return | |
def endElement(self, name): | |
return | |
def parsedocument(docstr1): | |
import re, xml.etree.ElementTree | |
mo=re.search('(<Properties Count="\d+">.*?</Properties>)',\ | |
docstr1, re.DOTALL) | |
if mo is not None: | |
propertiestree = xml.etree.ElementTree.fromstring(mo.group(1)) | |
d1=dict((p.attrib['name'],p[0].attrib['value']) \ | |
for p in propertiestree.getchildren() \ | |
if 'value' in p[0].attrib) | |
moversion=re.search('<Document SchemaVersion="(\d+)" ProgramVersion="(.*?)" FileVersion="(\d+)">',docstr1) | |
#re.search('<Document SchemaVersion="(\d+)"ProgramVersion="(.*?)" FileVersion="(\d+)">', docstr1,re.DOTALL) | |
if moversion is not None: | |
d1['ProgramVersion'] = moversion.group(2) | |
d1['SchemaFileVersion'] = \ | |
(moversion.group(1),moversion.group(3)) | |
return d1 | |
else: | |
return {} | |
def extractuidpropertiesdict(d1): | |
return d1.get('Uid') or d1.get('Id') | |
def extractuidstring(str1): | |
return extractuidpropertiesdict(parsedocument(str1)) | |
def extractuid(filename): | |
z=zipfile.ZipFile(filename) | |
uuid=extractuidstring(z.read('Document.xml')) | |
z.close() | |
return uuid | |
def git2datetime(ts,offset): | |
import datetime,dateutil.tz | |
utc=dateutil.tz.tzoffset(None,0) | |
local=dateutil.tz.tzoffset(None,offset) | |
dtutc=datetime.datetime.fromtimestamp(ts,utc) | |
return dtutc.astimezone(local) | |
def parsedatetime(datetimestr): | |
import calendar,dateutil.parser | |
dt=dateutil.parser.parse(datetimestr) | |
timestamp=calendar.timegm(dt.utctimetuple()) | |
utcoffset=dt.utcoffset() | |
if utcoffset is None: | |
return timestamp,0 | |
else: | |
return timestamp,utcoffset.total_seconds() | |
def uuidfilelist(filenames): | |
"""extract the UUID, LastModidiedDate and git tree hash form given | |
FCStd files""" | |
uuiddict={} | |
filelist=[] | |
for filepath in filenames: | |
if filepath.lower().endswith('.fcstd') or\ | |
filepath.lower().endswith('.fcstd1'): | |
treeid,propertiesdict=buildtree(filepath,object_store=None) | |
uuidstr = propertiesdict.get('Uid') or propertiesdict.get('Id') | |
doctimestamp=parsedatetime(\ | |
propertiesdict['LastModifiedDate'].strip()) | |
list1=uuiddict.get(uuidstr,[]) | |
list1.append((filepath,doctimestamp[0],treeid)) | |
uuiddict[uuidstr]=sorted(list1,key=lambda k:k[1]) | |
filelist.append((filepath, treeid, uuidstr, doctimestamp[0])) | |
return filelist,uuiddict | |
def uuiddir(paths=('.',)): | |
"""extract the UUID, LastModidiedDate and git tree hash form all | |
FCStd files in the given directories""" | |
import os | |
uuiddict={} | |
for path in paths: | |
for filename in os.listdir(path): | |
if filename.lower().endswith('.fcstd') or\ | |
filename.lower().endswith('.fcstd1'): | |
filepath=os.path.join(path,filename) | |
#listentry=extractuid(filepath,True) | |
treeid,propertiesdict=buildtree(filepath,object_store=None) | |
uuidstr = propertiesdict.get('Uid') or propertiesdict.get('Id') | |
doctimestamp=parsedatetime(\ | |
propertiesdict['LastModifiedDate'].strip()) | |
list1=uuiddict.get(uuidstr,[]) | |
list1.append((filepath,doctimestamp[0],treeid)) | |
uuiddict[uuidstr]=sorted(list1,key=lambda k:k[1]) | |
return uuiddict | |
def getFilesList(documentstr): | |
"""parse the FreeCAD xml document and extract the names of referenced | |
external files, in the order of apperanche. The FCStd file format expects | |
relies on the correct oder of the files inside the ZIP structure.""" | |
import xml.sax | |
handler=DocumentHandler() | |
xml.sax.parseString(documentstr,handler) | |
return tuple(iter(handler.files)) | |
def buildtree(filename,object_store=None): | |
"""Calculate the tree hash for a FCStd file | |
if an object_store is specified the blobs and tree will be added | |
the properties are returned as a dictionary""" | |
propertiesdict={} | |
z=zipfile.ZipFile(filename) | |
tree=dulwich.objects.Tree() | |
for i in z.infolist(): | |
if i.filename == 'Document.xml': | |
propertiesdict=parsedocument(z.open(i).read()) | |
elif i.filename.startswith('thumbnails/'): | |
continue # discard the thumbnailis. | |
#It's easier than handling tree objects | |
blob = dulwich.objects.Blob.from_string(z.open(i).read()) | |
if object_store is not None: | |
object_store.add_object(blob) | |
tree.add(i.filename, 0100644, blob.id) | |
z.close() | |
if object_store is not None: | |
object_store.add_object(tree) | |
return tree.id,propertiesdict | |
def walkrefs(repo,unknown=()): | |
unknown=set(unknown) | |
known=set() | |
while len(unknown) > 0: | |
#unknown=unknown-known | |
commit=unknown.pop() | |
try: | |
parents=repo.get_parents(commit) | |
known.add(commit) | |
unknown.update(frozenset(parents)-known) | |
except ValueError: | |
print "skipped invalid commit %s" % commit | |
#raise | |
return known | |
def treeids(repo): | |
def addtodictset(d,k,v): | |
s=d.get(k,set()) | |
s.add(v) | |
d[k]=s | |
ref2tree={} | |
tree2currentref={} | |
tree2parentref={} | |
for refname, commit in repo.get_refs().iteritems(): | |
try: | |
currenttree=repo.get_object(commit).tree | |
addtodictset(tree2currentref,currenttree,refname) | |
commits=walkrefs(repo,(commit,)) #walks parents! | |
trees=[repo.get_object(commitid).tree for commitid in commits-\ | |
frozenset(commit)] | |
ref2tree[refname]=[currenttree]+trees | |
for tree in trees: | |
addtodictset(tree2parentref,tree,'parent_of_%s' %refname) | |
except ValueError: | |
raise | |
print "skipped invalid commit %s" % commit | |
return ref2tree,tree2currentref,tree2parentref | |
def tree2propertiesdict(treeid,repo): | |
tree = repo.get_object(treeid) | |
if 'Document.xml' in tree: | |
perms,blobid = tree['Document.xml'] | |
documentobj=repo.get_object(blobid) | |
return parsedocument(documentobj.data) | |
def checkoutfilecommitid(refid,zipfilepath=None,repopath='.',repo=None): | |
repo = repo or dulwich.repo.Repo(repopath) | |
commit=repo.get_object(refid) | |
tree=repo.get_object(commit.tree) | |
documentblob=None | |
guidocumentblob=None | |
for tentry in tree.items():#._entries:#tree.entries(): | |
#for attr,name,blobhash in tree.entries(): | |
name = tentry.path | |
blobhash = tentry.sha | |
if name == 'Document.xml' : documentblob = blobhash | |
elif name == 'GuiDocument.xml' : guidocumentblob = blobhash | |
namelist=['Document.xml'] | |
documentobj=repo.get_object(documentblob) | |
documentstr=documentobj.data | |
namelist.extend(getFilesList(documentstr)) | |
if guidocumentblob is not None: | |
guidocumentobj=repo.get_object(guidocumentblob) | |
namelist.append('GuiDocument.xml') | |
namelist.extend(getFilesList(guidocumentobj.data)) | |
namelist2=[] | |
for filename in namelist: | |
for treeentry in tree.items(): | |
if treeentry.path == filename: | |
namelist2.append((filename,treeentry.sha)) | |
#write the zipfile | |
if zipfilepath is None or zipfilepath is True: | |
if repopath.lower().endswith('.fcstd.git'): | |
zipfilepath=repopath[:-4] | |
elif zipfilepath is True: | |
import os.path #extract name | |
filename=parsedocument(documentstr).get('FileName') | |
zipfilepath=os.path.join(repopath,os.path.split(filename)[1]) | |
else: | |
import os | |
import os.path | |
zipfilepath=os.path.join(repopath,'%s.FCStd' % \ | |
(ref.replace('/','_'))) | |
#if os.path.exists(zipfilepath): | |
# zipfilepath='gitcheckout-%s' % zipfilepath | |
zf=zipfile.ZipFile(zipfilepath,'w',zipfile.ZIP_DEFLATED) | |
for filename,blobhash in namelist2: | |
zf.writestr(filename,repo.get_object(blobhash).data) | |
zf.close() | |
return zipfilepath | |
def checkoutfile(ref='HEAD',zipfilepath=None,repopath='.',\ | |
returncommitid=False): | |
repo=dulwich.repo.Repo(repopath) | |
refid = repo.refs.read_ref(ref) | |
if refid is None: | |
refid = repo.refs.read_ref('refs/heads/%s' % ref) | |
if refid is None and len(ref) == 40: | |
refid=ref | |
if refid is None: | |
raise ValueError('Neither refs nor full hash given. Use git rev-parse to get the full hash') | |
filename = checkoutfilecommitid(refid,zipfilepath=zipfilepath,\ | |
repopath=repopath,repo=repo) | |
if returncommitid: | |
return filename,commit #to save as parent for next commit | |
else: | |
return filename #backward compatible | |
def commitfile(filename,refname=None,repopath='.',overrideparents=None\ | |
,defaultauthor=None,committimestamp=None,checkforduplicatetree=\ | |
True): | |
"""decompress a FreeCAD file and check it into the repo""" | |
import os.path | |
filename2=os.path.split(filename)[1].rsplit('.',1)[0] | |
if refname is None: | |
refname = filename2.replace(' ','_') | |
repo=dulwich.repo.Repo(repopath) | |
object_store = repo.object_store | |
treeid,propertiesdict = buildtree(filename,object_store=object_store) | |
datetimestr=propertiesdict['LastModifiedDate'].strip() | |
uuidstr=propertiesdict.get('Uid') or \ | |
propertiesdict.get('Id') | |
if 'Uid' in propertiesdict: | |
del propertiesdict['Uid'] | |
if 'Id' in propertiesdict: | |
del propertiesdict['Id'] | |
if 'SchemaFileVersion' in propertiesdict: | |
del propertiesdict['SchemaFileVersion'] | |
author=propertiesdict['LastModifiedBy'].strip() | |
keys=sorted(propertiesdict.keys()) | |
propertiesstr='\n'.join(('%s: %s' % (key,\ | |
propertiesdict[key].strip()) \ | |
for key in keys if propertiesdict[key].strip())) | |
doctimestamp=parsedatetime(datetimestr) | |
#doctimestamp=calendar.timegm(time.struct_time(i.date_time+(0,0,0))) | |
author = author or defaultauthor or 'unknown' | |
if not author.endswith('>'): | |
author = '%s <>' % author | |
commit = dulwich.objects.Commit() | |
commit.tree=treeid | |
commit.author = author | |
commit.committer = defaultcommiter | |
import time | |
commit.author_time = int(doctimestamp[0]) | |
commit.author_timezone = doctimestamp[1] | |
if committimestamp is None: | |
commit.commit_time = int(time.time()) | |
commit.commit_timezone = -1 * time.timezone # use the current timezone | |
else: | |
commit.commit_time = int(committimestamp[0]) | |
commit.commit_timezone = committimestamp[1] | |
#unix timestamp parse form from xml | |
#tz = dulwhich.parse_timezone('+0100')[0] # ??? | |
#commit.author_timezone = 0 #tz | |
#commit.encoding = "UTF-8" | |
ref= 'refs/heads/%s'%refname#.\ | |
# decode('utf-8').encode('ascii',errors='replace').replace('?','_') | |
uuidrefname = 'refs/heads/%s'%uuidstr | |
olduuidrefid = repo.refs.read_ref(uuidrefname) | |
oldnamerefid = repo.refs.read_ref(ref) | |
if overrideparents is not None: | |
parents = set(overrideparents) | |
else: | |
parents = set() | |
if olduuidrefid is not None: | |
parents.add(olduuidrefid) | |
if oldnamerefid is not None: | |
parents.add(oldnamerefid) | |
if len(parents) ==1 and checkforduplicatetree: | |
parentcommit=repo.get_object(tuple(parents)[0]) | |
parenttree=parentcommit.tree | |
if parenttree == treeid: | |
print "Warning: skipped duplicate tree" | |
return False #commit would be empty | |
if len(parents) > 0: | |
commit.parents=list(parents) | |
neworupdate='Updated' | |
else: | |
neworupdate='New' | |
commit.message = ('%s FreeCAD Document %s\n\n'\ | |
'UUID: %s\n\n%s\n' % ( neworupdate, filename2, uuidstr,propertiesstr))\ | |
.encode('utf-8') | |
object_store.add_object(commit) | |
repo.refs[ref]= commit.id | |
if repo.bare: | |
repo.refs['refs/heads/master']=commit.id | |
if olduuidrefid is None or olduuidrefid in parents: | |
repo.refs[uuidrefname] = commit.id | |
else: | |
print "Warning: updating the UUID-ref would create orphan commits" | |
if oldnamerefid is not None and oldnamerefid not in parents: | |
print "Probably orphaned commit: %s" % oldnamerefid | |
return commit.id | |
def saveandcommit(doc=None,repodir=None,save=True): | |
import FreeCAD,os | |
if doc is None: | |
doc=FreeCAD.activeDocument() | |
if doc is None or not doc.FileName: | |
raise ValueError('No Document or no Filename set') | |
if save: | |
doc.save() | |
filename=doc.FileName | |
if hasattr(FreeCAD,'_doc2git'): | |
repodir = repodir or FreeCAD._doc2git.get('repopath') | |
branch = FreeCAD._doc2git.get('branch') | |
parents = FreeCAD._doc2git.get('parents') | |
path,name=os.path.split(filename) | |
if repodir is None: | |
try: #test if path is a also a git repo | |
repo=dulwich.repo.Repo(path) | |
repodir=path | |
except dulwich.repo.NotGitRepository: | |
repodir='%s.git' % filename | |
if not os.path.isdir(repodir): | |
os.mkdir(repodir) | |
try: | |
repo=dulwich.repo.Repo(repodir) | |
except dulwich.repo.NotGitRepository: | |
repo=dulwich.repo.Repo.init_bare(repodir) | |
#commitfile(filename,refname=None,repopath='.',overrideparents=None\ | |
# ,defaultauthor=None,committimestamp=None): | |
commitid = commitfile(filename,repopath=repodir,refname=branch, | |
overrideparents=parents) | |
if not hasattr(FreeCAD,'_doc2git'): | |
FreeCAD._doc2git={doc:{'repopath':repodir,'branch':branch}} | |
FreeCAD._doc2git[doc]['parents']=[commitid] | |
return commitid | |
def checkoutandload(ref='master',repopath='.'): | |
try: #test if path is a also a git repo | |
repo=dulwich.repo.Repo(repopath) | |
if ref is None: #check if all branches point to the same commit/tree | |
ref2tree,tree2currentref,tree2parentref = treeids(repo) | |
if len(tree2currentref) ==1: #all refs contain the same root tree | |
ref=ref2tree.keys()[0] | |
else: | |
raise ValueError('multiple branches in repo') | |
import FreeCAD | |
filename,commitid=checkoutfile(ref=ref,zipfilepath=None,\ | |
repopath=repopath,returncommitid=True) | |
doc=FreeCAD.openDocument(filename) | |
if not hasattr(FreeCAD,'_doc2git'): | |
FreeCAD._doc2git={} | |
FreeCAD._doc2git[doc]={'repopath':repopath,'branch':ref,\ | |
parents:[commitid]} | |
except dulwich.repo.NotGitRepository: | |
raise | |
def _example_check_for_existing_tree(): | |
repo=dulwich.repo.Repo('.') | |
ref2tree,tree2currentref,tree2parentref = treeids(repo) | |
#print tree2ref | |
uuiddict=uuiddir(('.','../Downloads')) | |
for key,value in uuiddict.iteritems(): | |
#print 'UUID %s' % key | |
for filename,timestamp,treeid in value: | |
if treeid in tree2currentref: | |
print key,filename,'CURRENT',tree2currentref[treeid] | |
if treeid in tree2parentref: | |
print key,filename,'parrent',tree2parentref[treeid] | |
#print treeid[:7],timestamp,filename,tree2ref.get(treeid) | |
def _example_check_in_all_files_with_given_UUID(): | |
"""checkin all versions of given UUID from a directory""" | |
uuiddict=uuiddir(('.','../Downloads')) | |
for uuidstr,refname in (\ | |
("83f098be-a2a6-4527-8ef1-1d2a3a379f19",'hydrophonics'), | |
("0c776e1b-8dca-49a5-b7f6-8f0484798e2a","gal")): | |
for filename, timestamp,treeid in uuiddict[uuidstr]: | |
print treeid[:7],timestamp,refname, filename | |
commitfile(filename,refname=refname) | |
if __name__ == '__main__': | |
import argparse | |
parser =argparse.ArgumentParser() | |
parser.add_argument("--no-parents", action='store_true', help =\ | |
"for the commti to have no parents, this might orphan existing" | |
"commits") | |
parser.add_argument("-a", "--author", help =\ | |
"set default author for files that Last Modified By Property") | |
parser.add_argument("-b", "--branch", help =\ | |
"branch name") | |
parser.add_argument("-c", "--checkout", action='store_true', help =\ | |
"checkout ") | |
parser.add_argument("-r", "--repo-path", default='.', help =\ | |
"path to the git repo") | |
parser.add_argument("-s", "--store", action='store_true', help =\ | |
"stores the file in the repo") | |
parser.add_argument("--tree-in-repo", action='store_true', help =\ | |
"checks if the files given are allready present in the repo") | |
parser.add_argument("--info", action='store_true', help =\ | |
"show properties of the FCStd files") | |
parser.add_argument("--test1", action='store_true', help =\ | |
"run test1 ") | |
parser.add_argument("files", nargs=argparse.REMAINDER) | |
args = parser.parse_args() | |
print args | |
if args.store: | |
for filename in args.files: | |
print filename | |
if args.no_parents: | |
overrideparents=() | |
else: | |
overrideparents=None | |
commitfile(filename,refname=args.branch,repopath=args.repo_path\ | |
,overrideparents=overrideparents,defaultauthor=\ | |
args.author) | |
elif args.checkout: | |
refname = args.branch or 'master' | |
checkoutfile(ref=refname,zipfilepath=None,repopath=args.repo_path) | |
elif args.tree_in_repo: | |
repo=dulwich.repo.Repo(args.repo_path) | |
ref2tree,tree2currentref,tree2parentref = treeids(repo) | |
filelist,uuiddict= uuidfilelist(args.files) | |
import time | |
for filepath, treeid, uuidstr, ts in filelist: | |
if treeid in tree2currentref or treeid in tree2parentref: | |
print '%s %s %s is present' % (treeid[:7],time.strftime("%F",\ | |
time.gmtime(ts)), filepath) | |
if treeid in tree2currentref: | |
print 'as current head of refs:',tree2currentref[treeid] | |
if treeid in tree2parentref: | |
print 'as parents in refs:',tree2parentref[treeid] | |
elif args.info: | |
for filename in args.files: | |
z=zipfile.ZipFile(filename) | |
docstr=z.open('Document.xml').read() | |
propertiesdict=parsedocument(docstr) | |
print propertiesdict | |
elif args.test1: | |
_example_check_for_existing_tree() | |
else: #list branches | |
repo=dulwich.repo.Repo(args.repo_path) | |
ref2tree,tree2currentref,tree2parentref = treeids(repo) | |
#print ref2tree | |
for key,value in tree2currentref.iteritems(): | |
print key[:7], ','.join(value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How does one actually use it?
I copied all 4 files to my user macros dir.
I installed dulwich from git.
Then when it still wasn't found I copied /opt/brew/bin/dulwich to dulwitch.py in my macros dir. It's only a tiny py file that loads something else, but I can't tell where it looks, so it was no surprise that it still failed.
So when it failed with a message that it couldn't find dulwich--0.12.1... , I poked around my system at random and in the dulwich source tree I took a wild undocumented stab in that dark that the only thing that looked like it even might be, or contain, the missing suff is this "*.egg" in a build directory. Having no idea what I was really doing, I copied the .egg file to the freecad user macros dir.
I tried to execute "checkoutgui", but it just said can not load porcelain.
I have a few freecad files in a git repo already, whole freecad files with compression level 0, not unzipped freecad files.
So I tried to execute "checkoutandload" and select that git directory, but it just said "repo contains multiple branches" which yes, it does.
So I tried going the other way, I loaded a freecad file, and then tried to execute "saveandcommit", but it just said "variable branch used before assignment".
Ok so I guess I have to somehow tell the script what branch to use. I guess with a config file or some other way to set that variable?
It seems like a lot of cool work, but for lack of the teeniest bit of explanation, I can't actually make use of any of it.