Created
June 3, 2017 23:25
-
-
Save theVDude/d428e4ceb71a7d9ed878ea149061ad82 to your computer and use it in GitHub Desktop.
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
# uncompyle6 version 2.9.8 | |
# Python bytecode 2.6 (62161) | |
# Decompiled from: Python 3.6.0 (default, Jan 16 2017, 13:35:36) | |
# [GCC 6.3.1 20170109] | |
# Embedded file name: ./sublimerge/sublimerge_differ.py | |
# Compiled at: 2016-10-17 14:46:21 | |
"""Copyright (c) Borys Forytarz. All rights reserved""" | |
import difflib | |
import re | |
import sublime | |
import time | |
import codecs | |
import os | |
import sys | |
import uuid | |
import platform | |
import codecs | |
import shutil | |
from hashlib import sha1 | |
from webbrowser import open_new_tab as browser_open | |
from base64 import decodestring as bd | |
from base64 import decodestring as decode64 | |
from base64 import encodestring as encode64 | |
from .sublimerge_utils import SublimergeUtils, splitlines | |
from .sublimerge_messages import SublimergeMessages | |
from .sublimerge_settings import SublimergeSettings | |
from .version import version | |
from .sublimerge_debug import console_log | |
signature = 'aHR0cDovL3d3dy5zdWJsaW1lcmdlLmNvbS9idXkuaHRtbA' | |
verify = 'U3VibGltZXJnZS5zdWJsaW1lLWxpY2Vuc2U' | |
evaled = 'U3VibGltZXJnZQ0KDQpJdCBzZWVtcyB1bmxpY2Vuc2VkIGNvcHkgaXMgaW4gdXNlIGZvciBtb3JlIHRoYW4gOTAgZGF5cy4gSSBiZWxpZXZlIHRoYXQgaXQgaGVscHMgYSBsb3QgaW4geW91ciB3b3JrLiBEZXZlbG9wbWVudCBvZiB0aGlzIHBhY2thZ2UgYWxzbyBjb3N0cyBtZSBhIGxvdCBvZiBlZmZvcnQgYW5kIG15IHNwYXJlIHRpbWUuIFBsZWFzZSBiZSBmYWlyIGFuZCBsZWdhbCBhbmQgcHVyY2hhc2UgYSBsaWNlbnNlLiBUaGFuayB5b3UgaW4gYWR2YW5jZS4NCg0KQm9yeXMgRm9yeXRhcnogLSBhdXRob3I=' | |
purc = 'UHVyY2hhc2Ugbm93' | |
utils = SublimergeUtils() | |
def fopen(path, mode): | |
try: | |
return open(path, mode) | |
except: | |
return codecs.open(path, mode) | |
def get_hunk_type(hunk1, hunk2): | |
if hunk1[1] == 0: | |
return '-' | |
elif hunk2[1] == 0: | |
return '+' | |
else: | |
return '.' | |
def prepare_text_for_diff(text): | |
if SublimergeSettings.get('ignore_crlf'): | |
text = re.sub('\r\n', '\n', text) | |
text = re.sub('\r', '\n', text) | |
if SublimergeSettings.get('ignore_whitespace'): | |
regexp = re.compile('(^[ \t\x0c\x0b]+)|([ \t\x0c\x0b]+$)', re.MULTILINE) | |
text = re.sub(regexp, '', text) | |
if SublimergeSettings.get('ignore_case'): | |
text = text.lower() | |
return text + '\nEOF' | |
class SublimergeDiffer(): | |
zero_offset = 0 | |
def __init__(self): | |
if int(sublime.version()) >= 3000: | |
self.zero_offset = self.diff_test() | |
def diff_test(self): | |
data = self.difference('a\nb\n\\c\n\\d', 'a\n\\c\n\\d', False) | |
if data['left'][0][0] != data['right'][0][0]: | |
return 1 | |
return 0 | |
def difference(self, text1, text2, separate_missing_blocks=False, callback=None, callback_done=None, their_crlf=False, mine_crlf=False): | |
if not isinstance(text1, list): | |
lines1 = splitlines(prepare_text_for_diff(utils.normalize_crlf(text1, their_crlf))) | |
else: | |
lines1 = text1 | |
if not isinstance(text2, list): | |
lines2 = splitlines(prepare_text_for_diff(utils.normalize_crlf(text2, mine_crlf))) | |
else: | |
lines2 = text2 | |
gen = difflib.unified_diff(lines1, lines2, n=0) | |
hunk_re = '^@@ \\-(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@' | |
data = {'left': [],'right': []} | |
def prepare(start_left, size_left, start_right, size_right): | |
end_left = size_left + start_left - 1 | |
end_right = size_right + start_right - 1 | |
type_left = type_right = '.' | |
if end_left < start_left: | |
type_left = '+' | |
type_right = '-' | |
elif end_right < start_right: | |
type_right = '+' | |
type_left = '-' | |
self.add(data['left'], [ | |
start_left, | |
end_left, | |
0 if size_left > size_right else size_right - size_left, | |
type_left]) | |
self.add(data['right'], [ | |
start_right, | |
end_right, | |
0 if size_right > size_left else size_left - size_right, | |
type_right]) | |
if callback is not None: | |
callback(data['left'][-1], data['right'][-1]) | |
return | |
for line in gen: | |
hunks = re.finditer(hunk_re, line) | |
for hunk in hunks: | |
start_left = int(hunk.group(1)) | |
start_right = int(hunk.group(3)) | |
size_left = int(hunk.group(2) or 1) | |
size_right = int(hunk.group(4) or 1) | |
if size_left > 0: | |
size_left < size_right and separate_missing_blocks and prepare(start_left, size_left, start_right, size_left) | |
prepare(start_left + size_left - self.zero_offset, 0, start_right + size_left, size_right - size_left) | |
elif size_right > 0: | |
size_right < size_left and separate_missing_blocks and prepare(start_left, size_right, start_right, size_right) | |
prepare(start_left + size_right, size_left - size_right, start_right + size_right - self.zero_offset, 0) | |
else: | |
prepare(start_left, size_left, start_right, size_right) | |
if callback_done is not None: | |
callback_done() | |
return data | |
def add(self, collection, data): | |
if data[1] < data[0]: | |
data[1] = 0 | |
if data[1] == 0: | |
data[0] += self.zero_offset | |
collection.append(data) | |
class SublimergeDiffer3(): | |
changes = [] | |
unmatched = [] | |
def difference(self, their, base, mine, callback, callback_merged, callback_done, their_crlf=False, base_crlf=False, mine_crlf=False): | |
self.their_original = splitlines(utils.normalize_crlf(their)) | |
self.mine_original = splitlines(utils.normalize_crlf(mine)) | |
self.their_original.append('\n') | |
self.mine_original.append('\n') | |
self.their = splitlines(prepare_text_for_diff(utils.normalize_crlf(their, their_crlf))) | |
self.base = splitlines(prepare_text_for_diff(utils.normalize_crlf(base, base_crlf))) | |
self.mine = splitlines(prepare_text_for_diff(utils.normalize_crlf(mine, mine_crlf))) | |
self.callback = callback | |
self.callback_merged = callback_merged | |
self.changes = [] | |
self.unmatched = {'their': [],'mine': []} | |
def hunk_line_set--- This code section failed: --- | |
188 0 LOAD_FAST 0 'hunk' | |
3 LOAD_CONST 1 1 | |
6 BINARY_SUBSCR | |
7 LOAD_CONST 2 '' | |
10 COMPARE_OP 2 '==' | |
13 JUMP_IF_FALSE 54 'to 70' | |
16 POP_TOP | |
189 17 LOAD_GLOBAL 0 'set' | |
20 LOAD_GLOBAL 1 'range' | |
23 LOAD_FAST 0 'hunk' | |
26 LOAD_CONST 2 '' | |
29 BINARY_SUBSCR | |
30 LOAD_FAST 0 'hunk' | |
33 LOAD_CONST 2 '' | |
36 BINARY_SUBSCR | |
37 LOAD_CONST 1 1 | |
40 BINARY_ADD | |
41 LOAD_FAST 1 'add_hunk_2' | |
44 JUMP_IF_TRUE 7 'to 54' | |
47 POP_TOP | |
48 LOAD_CONST 2 '' | |
51 JUMP_FORWARD 8 'to 62' | |
54_0 COME_FROM '44' | |
54 POP_TOP | |
55 LOAD_FAST 0 'hunk' | |
58 LOAD_CONST 3 2 | |
61 BINARY_SUBSCR | |
62_0 COME_FROM '51' | |
62 BINARY_ADD | |
63 CALL_FUNCTION_2 2 | |
66 CALL_FUNCTION_1 1 | |
69 RETURN_END_IF | |
70 POP_TOP | |
191 71 LOAD_GLOBAL 0 'set' | |
74 LOAD_GLOBAL 1 'range' | |
77 LOAD_FAST 0 'hunk' | |
80 LOAD_CONST 2 '' | |
83 BINARY_SUBSCR | |
84 LOAD_FAST 0 'hunk' | |
87 LOAD_CONST 1 1 | |
90 BINARY_SUBSCR | |
91 LOAD_CONST 1 1 | |
94 BINARY_ADD | |
95 LOAD_FAST 1 'add_hunk_2' | |
98 JUMP_IF_TRUE 7 'to 108' | |
101 POP_TOP | |
102 LOAD_CONST 2 '' | |
105 JUMP_FORWARD 8 'to 116' | |
108_0 COME_FROM '98' | |
108 POP_TOP | |
109 LOAD_FAST 0 'hunk' | |
112 LOAD_CONST 3 2 | |
115 BINARY_SUBSCR | |
116_0 COME_FROM '105' | |
116 BINARY_ADD | |
117 CALL_FUNCTION_2 2 | |
120 CALL_FUNCTION_1 1 | |
123 RETURN_VALUE | |
Parse error at or near `COME_FROM' instruction at offset 54_0 | |
def hunk_line_range(hunk): | |
if hunk[1] == 0: | |
return (hunk[0], hunk[0] + 1) | |
else: | |
return ( | |
hunk[0], hunk[1] + 1) | |
def add_their_base(base_hunk, their_hunk): | |
for change in self.changes: | |
if hunk_line_set(change['their']) & hunk_line_set(their_hunk): | |
change['base_their'] = base_hunk | |
def is_conflict(change): | |
return hunk_line_set(change['base_their'], True) & hunk_line_set(change['base_mine'], True) or hunk_line_set(change['their']) & hunk_line_set(change['mine']) | |
def add_mine_base(base_hunk, mine_hunk): | |
for change in self.changes: | |
if hunk_line_set(change['mine']) & hunk_line_set(mine_hunk): | |
change['base_mine'] = base_hunk | |
elif change['base_their'] is not None: | |
if is_conflict(change): | |
change['conflict'] = True | |
return | |
def verify_conflict(change): | |
their_insert = change['their'][1] == 0 | |
mine_insert = change['mine'][1] == 0 | |
if not their_insert: | |
text_their = not mine_insert and self.their[change['their'][0] - 1:change['their'][1]] | |
text_base = self.base[change['their'][0] - 1:change['their'][1]] | |
text_their == text_base and console_log('Resolving conflict using `mine` because `their` == `base`', text_their, text_base) | |
change['conflict'] = False | |
change['base_their'] = None | |
return | |
else: | |
text_mine = self.mine[change['mine'][0] - 1:change['mine'][1]] | |
text_base = self.base[change['mine'][0] - 1:change['mine'][1]] | |
if text_mine == text_base: | |
console_log('Resolving conflict using `their` because `mine` == `base`', text_mine, text_base) | |
change['conflict'] = False | |
change['base_mine'] = None | |
return | |
if SublimergeSettings.get('three_way_auto_resolve')['white_space_vs_non_white_space']: | |
if all((char in ('\r', '\n', '\t', ' ') for char in text_mine)): | |
console_log('Resolving conflict using `their` because `mine` contains only empty lines', text_mine, text_their) | |
change['base_mine'] = None | |
change['their'][3] = change['mine'][3] = '?' | |
return | |
else: | |
all((char in ('\r', '\n', '\t', ' ') for char in text_their)) and console_log('Resolving conflict using `mine` because `their` contains only empty lines', text_their, text_mine) | |
change['base_their'] = None | |
change['their'][3] = change['mine'][3] = '?' | |
return | |
elif their_insert and not mine_insert or not their_insert and mine_insert: | |
change['conflict'] = False | |
if their_insert: | |
change['base_mine'] = None | |
console_log('Resolving conflict using `their` because of single-side insertion') | |
else: | |
change['base_their'] = None | |
console_log('Resolving conflict using `mine` because of single-side insertion') | |
return | |
change['their'][3] = change['mine'][3] = '!' | |
return | |
SublimergeDiffer().difference(self.their, self.mine, callback=lambda hunk_their, hunk_mine: self.changes.append({'their': hunk_their, | |
'mine': hunk_mine, | |
'base_their': None, | |
'base_mine': None, | |
'conflict': False | |
})) | |
SublimergeDiffer().difference(self.base, self.their, callback=add_their_base) | |
SublimergeDiffer().difference(self.base, self.mine, callback=add_mine_base) | |
merged_hunks = [] | |
merged = [] | |
last_change = None | |
last_text = None | |
last_end = None | |
whose = 'mine' | |
text = self.mine_original | |
for change in self.changes: | |
console_log('Change', change) | |
if change['conflict']: | |
verify_conflict(change) | |
if not change['conflict'] or change['their'][3] == '?': | |
if change['base_mine'] is None: | |
whose = 'their' | |
text = self.their_original | |
else: | |
whose = 'mine' | |
text = self.mine_original | |
else: | |
change['their'][3] = change['mine'][3] | |
change_line_begin = change[whose][0] - 1 | |
change_line_end = change[whose][0] if change[whose][1] == 0 else change[whose][1] | |
if last_change is not None: | |
if last_change[whose][1] == 0: | |
if change[whose][1] == 0: | |
begin = last_change[whose][0] | |
end = change[whose][0] - 1 | |
elif last_change[whose][1] == 0: | |
begin = last_change[whose][0] | |
end = change[whose][0] - 1 | |
else: | |
begin = last_change[whose][1] + 1 | |
end = change[whose][0] - 1 | |
merged += text[begin - 1:end] | |
else: | |
merged += text[0:change_line_begin] | |
merged_lines = len(merged) | |
hunk = change[whose][:] | |
if hunk[1] > 0: | |
hunk[1] = merged_lines + (hunk[1] - hunk[0]) + 1 | |
hunk[0] = merged_lines + 1 | |
if (not change['conflict'] or change[whose][3] == '?') and change[whose][1] != 0: | |
merged += text[change_line_begin:change_line_end] | |
else: | |
their = change['their'][:] | |
mine = change['mine'][:] | |
hunk[2] = max(their[1] - their[0], mine[1] - mine[0]) + 1 | |
hunk[1] = 0 | |
merged_hunks.append(hunk) | |
last_change = change | |
last_text = text | |
last_end = change_line_end | |
self.callback(change['their'], change['mine']) | |
off = 0 | |
self.their_original.pop() | |
self.mine_original.pop() | |
if last_change is not None: | |
off = 1 if last_change[whose][1] == 0 else 0 | |
merged += last_text[last_end - off:] | |
else: | |
merged = self.mine_original[:] | |
if len(merged) > 0 and len(self.their_original) > 0 and len(self.mine_original) > 0: | |
nl_chars = [ | |
'\r', '\n'] | |
if merged[-1] in nl_chars: | |
merged = merged[0:-1] | |
else: | |
if merged[-1] != '': | |
if merged[-1][-1] in nl_chars: | |
merged[-1] = not (self.their_original[-1][-1] in nl_chars and self.mine_original[-1][-1] in nl_chars) and merged[-1][0:-1] | |
self.callback_merged(''.join(merged), merged_hunks) | |
callback_done is not None and callback_done() | |
return | |
def b64d(txt): | |
if int(sublime.version()) < 3000: | |
return decode64(txt + '==') | |
else: | |
return str(decode64(bytes(txt + '==', 'utf-8')).decode('utf-8')) | |
def b64e(txt): | |
if int(sublime.version()) < 3000: | |
return encode64(txt).replace('\n', '').replace('=', '') | |
else: | |
return str(encode64(bytes(txt, 'utf-8')).decode('utf-8')).replace('\n', '').replace('=', '') | |
def r_sh(text, os_fp): | |
key = sha1(str(os_fp).encode('utf-8')).hexdigest() | |
enc = [] | |
for i in range(len(text)): | |
key_c = key[i % len(key)] | |
enc_c = chr((ord(text[i]) + ord(key_c)) % 256) | |
enc.append(enc_c) | |
return b64e(''.join(enc)) | |
def r_us(text, os_fp): | |
key = sha1(str(os_fp).encode('utf-8')).hexdigest() | |
dec = [] | |
text = b64d(text) | |
for i in range(len(text)): | |
key_c = key[i % len(key)] | |
dec_c = chr((256 + ord(text[i]) - ord(key_c)) % 256) | |
dec.append(dec_c) | |
return ''.join(dec) | |
class SublimergeDifferencer(): | |
types = [ | |
'y', 'm', 'f'] | |
rev = [ | |
'1d40462e0bc18d029ab54ac5cb9796933bfe18b4', | |
'c926ded08c9d6608c26cd9d82c6e78e52057f816'] | |
def __init__(self): | |
self.fp = None | |
self.installed = None | |
self.fp_fixed = False | |
base_path = os.path.realpath(os.path.join(sublime.packages_path(), '..')) | |
path = os.path.join(base_path, 'Settings') | |
if not os.path.exists(path): | |
path = os.path.join(base_path, 'Local') | |
if not os.path.exists(path): | |
path = base_path | |
if not os.path.exists(path): | |
path = SublimergeRuntime.my_dir | |
self.installed_path = os.path.join(path, '.id' + self.os_fp()) | |
if not os.path.exists(self.installed_path): | |
for f in os.listdir(path): | |
file_path = os.path.join(path, f) | |
if os.path.isfile(file_path): | |
self.fp_fixed = f.startswith('.id') and ( | |
self.fp, self.installed_path) | |
self.installed_path = file_path | |
self.fp = f[3:] | |
else: | |
break | |
reg = sublime.load_settings(self.rf()) | |
k = reg.get('key', None) | |
if k: | |
re.match('^([A-Z0-9]{4}-){9}[A-Z0-9]{4}$', k) and self.ik(k) | |
return | |
def os_fp(self): | |
if self.fp is None: | |
sb = [] | |
try: | |
arch = platform.architecture() | |
sb.append(platform.node()) | |
sb.append(arch[0]) | |
sb.append(arch[1]) | |
sb.append(platform.machine()) | |
sb.append(platform.processor()) | |
sb.append(platform.system()) | |
except: | |
pass | |
sb.append(sublime.packages_path()) | |
sb.append(sublime.installed_packages_path()) | |
self.fp = sha1('#'.join(sb).encode('utf-8')).hexdigest() | |
return self.fp | |
def bd(self, txt): | |
if int(sublime.version()) < 3000: | |
return bd(txt + '==') | |
else: | |
return str(bd(bytes(txt + '==', 'utf-8')).decode('utf-8')) | |
def rf(self): | |
return self.bd(verify) | |
def rm(self, force=False): | |
if force or sublime.ok_cancel_dialog(SublimergeMessages.UNREGISTERED): | |
self.orp() | |
def orp(self): | |
s = '?v=' + version + '&st=' + sublime.version() | |
browser_open(self.bd(signature) + s) | |
def gs(self): | |
reg = sublime.load_settings(self.rf()) | |
k = ko = reg.get('key', None) | |
if not k: | |
return False | |
tries = [ | |
self.os_fp(), uuid.getnode(), uuid.getnode(), uuid.getnode()] | |
decoded = False | |
for h in tries: | |
try: | |
k = r_us(ko, h) | |
k = b64d(k) | |
if k.startswith(self.fp.upper()): | |
decoded = True | |
break | |
except Exception, e: | |
pass | |
if not decoded: | |
return False | |
k = k[len(self.fp):] | |
if self.vr(k): | |
try: | |
if self.fp_fixed: | |
shutil.copy(self.installed_path, self.fp_fixed[1]) | |
self.fp, self.installed_path = self.fp_fixed | |
self.fp_fixed = False | |
self.ik(k) | |
except: | |
pass | |
return True | |
else: | |
return False | |
def enck(self, k): | |
k = b64e(self.fp.upper() + k) | |
k = r_sh(k, self.os_fp()) | |
return k | |
def ps(self): | |
sublime.active_window().show_input_panel(SublimergeMessages.ENTER_KEY, '', self.rr, None, None) | |
return | |
def rr(self, k): | |
k = k.strip() | |
if not self.vr(k): | |
sublime.error_message(SublimergeMessages.KEY_INVALID) | |
else: | |
self.ik(k) | |
sublime.message_dialog(SublimergeMessages.KEY_OK) | |
def ik(self, k): | |
reg = sublime.load_settings(self.rf()) | |
reg.set('key', self.enck(k) if k else False) | |
sublime.save_settings(self.rf()) | |
def unik(self): | |
if self.gs(): | |
self.ik(False) | |
sublime.message_dialog(SublimergeMessages.KEY_REMOVED) | |
def mix(self, input): | |
sha = sha1(input.encode('utf-8')).hexdigest() | |
_len = len(sha) | |
k = [' '] * _len | |
i = 0 | |
for letter in sha: | |
i += 1 | |
pos = ord(letter) * i % _len - i | |
while pos >= _len or k[pos] != ' ': | |
pos = pos + 1 | |
if pos >= _len: | |
pos = 0 | |
k[pos] = letter | |
return k | |
def mk(self, input, type): | |
letters = [ | |
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', | |
'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', | |
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', | |
'1', '2', '3', '4', '5', '6', '7', '8', | |
'9'] | |
k = '' | |
arr = self.mix(input + '@' + type) | |
i = 0 | |
while len(arr) > 0: | |
pair = arr[0:2] | |
arr = arr[2:] | |
move = int(''.join(pair), 16) | |
k = k + letters[move % len(letters) - 1] | |
i += 1 | |
if i % 4 == 0: | |
k += '-' | |
return k[0:-1].upper() | |
def vr(self, k): | |
if re.match('^([A-Z0-9]{4}-){9}[A-Z0-9]{4}$', k): | |
lines = [ | |
k[0:24], k[25:]] | |
if sha1(k.encode('utf-8')).hexdigest() in self.rev: | |
return False | |
for type in self.types: | |
if self.mk(lines[0], type) == lines[1]: | |
return type | |
return False | |
def us(self): | |
time_offset = 7776000 | |
try: | |
if not os.path.exists(self.installed_path): | |
f = fopen(self.installed_path, 'w') | |
f.write('%f' % time.time()) | |
f.close() | |
if self.installed is None: | |
f = fopen(self.installed_path, 'r') | |
self.installed = float(f.read()) | |
f.close() | |
if self.installed > time.time(): | |
self.installed = time.time() - time_offset | |
except: | |
self.installed = time.time() - time_offset | |
try: | |
time_d = time.time() - self.installed | |
if self.gs() is False: | |
if time_d >= time_offset: | |
sublime.ok_cancel_dialog(self.bd(evaled), self.bd(purc)) and self.orp() | |
return True | |
except Exception, e: | |
pass | |
return False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment