-
-
Save XenuIsWatching/66f5dc8760d948c09df9 to your computer and use it in GitHub Desktop.
MKS fast-import script for git
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/python | |
# | |
#Copyright (c) 2015 Ryan McClelland | |
# | |
#Permission is hereby granted, free of charge, to any person obtaining a copy | |
#of this software and associated documentation files (the "Software"), to deal | |
#in the Software without restriction, including without limitation the rights | |
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
#copies of the Software, and to permit persons to whom the Software is | |
#furnished to do so, subject to the following conditions: | |
# | |
#The above copyright notice and this permission notice shall be included in all | |
#copies or substantial portions of the Software. | |
# | |
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
#SOFTWARE. | |
# | |
# This can be called using either the windows python interpreter or the cygwin python interpreter | |
# | |
# HOW TO USE | |
# You must have python and si (mks command line tools) on the PATH variable | |
# make a folder for where you want your git repository to reside | |
# initialize the git repository by running "git init" | |
# next being the import | |
# from cygwin "./mks_checkpoints_to_git.py <MKS project path> | git fast-import" | |
# from windows "python mks_checkpoints_to_git.py <MKS project path> | git fast-import" | |
# | |
# Import MKS history into GIT | |
# Meant to be used with fast-import | |
# | |
# Currently imports checkpoints and development paths only... | |
# This does not currently support incremental imports | |
import os | |
from subprocess import Popen | |
from subprocess import PIPE | |
import time | |
import sys | |
import re | |
import platform | |
from datetime import datetime | |
# this is so windows doesn't output CR (carriage return) at the end of each line and just does LF (line feed) | |
if platform.system() == 'Windows': | |
import msvcrt | |
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) | |
def export_data(string): | |
print 'data %d\n%s' % (len(string), string) | |
def inline_data(filename, code = 'M', mode = '644'): | |
content = open(filename, 'r').read() | |
if platform.system() == 'Windows': | |
#this is a hack'ish way to get windows path names to work git (is there a better way to do this?) | |
filename = filename.replace('\\','/') | |
print "%s %s inline %s" % (code, mode, filename) | |
export_data(content) | |
def convert_revision_to_mark(revision): | |
if not revision in marks: | |
marks.append(revision) | |
return marks.index(revision) + 1 | |
def retrieve_revisions(devpath=0): | |
if devpath: | |
pipe = Popen('si viewprojecthistory --rfilter=devpath:"%s" --project="%s"' % (devpath, sys.argv[1]), shell=True, bufsize=1024, stdout=PIPE) | |
else: | |
pipe = Popen('si viewprojecthistory --rfilter=devpath::current --project="%s"' % sys.argv[1], shell=True, bufsize=1024, stdout=PIPE) | |
versions = pipe.stdout.read().split('\n') | |
versions = versions[1:] | |
version_re = re.compile('[0-9]([\.0-9])+') | |
revisions = [] | |
for version in versions: | |
match = version_re.match(version) | |
if match: | |
version_cols = version.split('\t') | |
revision = {} | |
revision["number"] = version_cols[0] | |
revision["author"] = version_cols[1] | |
revision["seconds"] = int(time.mktime(datetime.strptime(version_cols[2], "%b %d, %Y %I:%M:%S %p").timetuple())) | |
revision["description"] = version_cols[5] | |
revisions.append(revision) | |
revisions.reverse() # Old to new | |
re.purge() | |
return revisions | |
def retrieve_devpaths(): | |
pipe = Popen('si projectinfo --devpaths --noacl --noattributes --noshowCheckpointDescription --noassociatedIssues --project="%s"' % sys.argv[1], shell=True, bufsize=1024, stdout=PIPE) | |
devpaths = pipe.stdout.read() | |
devpaths = devpaths [1:] | |
devpaths_re = re.compile(' (.+) \(([0-9][\.0-9]+)\)\n') | |
devpath_col = devpaths_re.findall(devpaths) | |
re.purge() | |
return devpath_col | |
def export_to_git(revisions,devpath=0,ancestor=0): | |
for revision in revisions: | |
#revision_col = revision["number"].split('\.') | |
mark = convert_revision_to_mark(revision["number"]) | |
# Create a build sandbox for the version | |
os.system('si createsandbox --populate -R --project="%s" --projectRevision=%s tmp%d' % (sys.argv[1], revision["number"], mark)) | |
os.chdir('tmp%d' % mark) #the reason why a number is added to the end of this is because MKS can sometimes be a piece of crap and doesn't always drop the full file structure when it should, so they all should have unique names | |
if devpath: | |
print 'commit refs/heads/devpath/%s' % devpath | |
else: | |
print 'commit refs/heads/master' | |
print 'mark :%d' % mark | |
print 'committer %s <> %d +0100' % (revision["author"], revision["seconds"]) #Germany UTC time zone | |
export_data(revision["description"]) | |
if ancestor: | |
print 'from :%d' % convert_revision_to_mark(ancestor) #we're starting a development path so we need to start from it was originally branched from | |
ancestor = 0 #set to zero so it doesn't loop back in to here | |
print 'deleteall' | |
tree = os.walk('.') | |
for dir in tree: | |
for filename in dir[2]: | |
if (dir[0] == '.'): | |
fullfile = filename | |
else: | |
fullfile = os.path.join(dir[0], filename)[2:] | |
if (fullfile.find('.pj') != -1): | |
continue | |
if (fullfile[0:4] == ".git"): | |
continue | |
if (fullfile.find('mks_checkpoints_to_git') != -1): | |
continue | |
inline_data(fullfile) | |
# Drop the sandbox | |
os.chdir("..") | |
shortname=sys.argv[1].replace('"', '').split('/')[-1] | |
os.system("si dropsandbox -Y -f --delete=all tmp%d/%s" % (mark, shortname)) | |
marks = [] | |
devpaths = retrieve_devpaths() | |
revisions = retrieve_revisions() | |
export_to_git(revisions) #export master branch first!! | |
for devpath in devpaths: | |
devpath_revisions = retrieve_revisions(devpath[0]) | |
export_to_git(devpath_revisions,devpath[0].replace(' ','_'),devpath[1]) #branch names can not have spaces in git so replace with underscores |
@calebpowell Hey there, I've actually just now move to using a git repository. If you want to, you can submit a pull request for this at https://github.com/XenuIsWatching/mks_checkpoints_to_git
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for writing this script! I had trouble migrating binary files. Using 'rb' mode (line #57) to read the file does the trick: