@ -13,6 +13,7 @@ import sys
from collections import defaultdict
from collections import defaultdict
from contextlib import contextmanager
from contextlib import contextmanager
from functools import partial
from functools import partial
from os . path import exists
import git
import git
import magic
import magic
@ -78,7 +79,8 @@ def br(obj):
def guess_extension ( fullname , buffer ) :
def guess_extension ( fullname , buffer ) :
mime = magic . from_buffer ( buffer , mime = True )
# um corte de apenas 1024 impediu a detecção correta de .docx
mime = magic . from_buffer ( buffer [ : 4096 ] , mime = True )
extensao = EXTENSOES . get ( mime )
extensao = EXTENSOES . get ( mime )
if extensao is not None :
if extensao is not None :
return extensao
return extensao
@ -143,17 +145,21 @@ def get_conteudo_dtml_method(doc):
return doc [ ' raw ' ]
return doc [ ' raw ' ]
def enumerate_by_key_list ( folder , key_list , type_key ) :
def print_msg_poskeyerror ( id ) :
for entry in folder . get ( key_list , [ ] ) :
id , meta_type = entry [ ' id ' ] , entry [ type_key ]
try :
obj = br ( folder . get ( id , None ) )
except POSKeyError :
print ( ' # ' * 80 )
print ( ' # ' * 80 )
print ( ' # ' * 80 )
print ( ' # ' * 80 )
print ( ' ATENÇÃO: DIRETÓRIO corrompido: {} ' . format ( id ) )
print ( ' ATENÇÃO: DIRETÓRIO corrompido: {} ' . format ( id ) )
print ( ' # ' * 80 )
print ( ' # ' * 80 )
print ( ' # ' * 80 )
print ( ' # ' * 80 )
def enumerate_by_key_list ( folder , key_list , type_key ) :
for entry in folder . get ( key_list , [ ] ) :
id , meta_type = entry [ ' id ' ] , entry [ type_key ]
try :
obj = folder . get ( id , None )
except POSKeyError :
print_msg_poskeyerror ( id )
else :
else :
yield id , obj , meta_type
yield id , obj , meta_type
@ -169,9 +175,12 @@ def enumerate_btree(folder):
contagem_esperada = folder [ ' _count ' ] . value
contagem_esperada = folder [ ' _count ' ] . value
tree = folder [ ' _tree ' ]
tree = folder [ ' _tree ' ]
contagem_real = 0 # para o caso em que não haja itens
contagem_real = 0 # para o caso em que não haja itens
try :
for contagem_real , ( id , obj ) in enumerate ( tree . iteritems ( ) , start = 1 ) :
for contagem_real , ( id , obj ) in enumerate ( tree . iteritems ( ) , start = 1 ) :
obj , meta_type = br ( obj ) , type ( obj ) . __name__
meta_type = type ( obj ) . __name__
yield id , obj , meta_type
yield id , obj , meta_type
except POSKeyError :
print_msg_poskeyerror ( folder [ ' id ' ] )
# verificação de consistência
# verificação de consistência
if contagem_esperada != contagem_real :
if contagem_esperada != contagem_real :
print ( ' ATENÇÃO: contagens diferentes na btree: '
print ( ' ATENÇÃO: contagens diferentes na btree: '
@ -197,10 +206,10 @@ def logando_nao_identificados():
print ( ' # ' * 80 )
print ( ' # ' * 80 )
def dump_folder ( folder , path , salvar , enum = enumerate_folder ) :
def dump_folder ( folder , path , salvar , mtimes , enum = enumerate_folder ) :
name = folder [ ' id ' ]
name = folder [ ' id ' ]
path = os . path . join ( path , name )
path = os . path . join ( path , name )
if not os . path . exists ( path ) :
if not exists ( path ) :
os . makedirs ( path )
os . makedirs ( path )
for id , obj , meta_type in enum ( folder ) :
for id , obj , meta_type in enum ( folder ) :
# pula pastas *_old (presentes em várias bases)
# pula pastas *_old (presentes em várias bases)
@ -210,8 +219,20 @@ def dump_folder(folder, path, salvar, enum=enumerate_folder):
if dump == ' ? ' :
if dump == ' ? ' :
nao_identificados [ meta_type ] . append ( path + ' / ' + id )
nao_identificados [ meta_type ] . append ( path + ' / ' + id )
elif dump :
elif dump :
id_interno = dump ( obj , path , salvar )
if isinstance ( dump , partial ) and dump . func == dump_folder :
try :
dump ( br ( obj ) , path , salvar , mtimes )
except POSKeyError as e :
print_msg_poskeyerror ( id )
continue
else :
# se o objeto for mais recente que o da última exportação
mtime = obj . _p_mtime
fullname = os . path . join ( path , id )
if mtime > mtimes . get ( fullname , 0 ) :
id_interno = dump ( br ( obj ) , path , salvar )
assert id == id_interno
assert id == id_interno
mtimes [ fullname ] = mtime
return name
return name
@ -223,7 +244,7 @@ def read_sde(element):
def read_properties ( ) :
def read_properties ( ) :
for id , obj , meta_type in enumerate_properties ( element ) :
for id , obj , meta_type in enumerate_properties ( element ) :
yield id , decode_iso8859 ( obj )
yield id , decode_iso8859 ( br ( obj ) )
def read_children ( ) :
def read_children ( ) :
for id , obj , meta_type in enumerate_folder ( element ) :
for id , obj , meta_type in enumerate_folder ( element ) :
@ -237,7 +258,7 @@ def read_sde(element):
# ignoramos os scrips python de eventos dos templates
# ignoramos os scrips python de eventos dos templates
yield { ' id ' : id ,
yield { ' id ' : id ,
' meta_type ' : meta_type ,
' meta_type ' : meta_type ,
' dados ' : read_sde ( obj ) }
' dados ' : read_sde ( br ( obj ) ) }
data = dict ( read_properties ( ) )
data = dict ( read_properties ( ) )
children = list ( read_children ( ) )
children = list ( read_children ( ) )
@ -302,6 +323,7 @@ def find_sapl(app):
sapl = br ( app [ ' sapl ' ] )
sapl = br ( app [ ' sapl ' ] )
return sapl
return sapl
<< << << < HEAD
def detectar_encoding ( fonte ) :
def detectar_encoding ( fonte ) :
desc = magic . from_buffer ( fonte )
desc = magic . from_buffer ( fonte )
@ -318,7 +340,23 @@ def autodecode(fonte):
else :
else :
return fonte
return fonte
def detectar_encoding ( fonte ) :
desc = magic . from_buffer ( fonte )
for termo , enc in [ ( ' ISO-8859 ' , ' latin1 ' ) , ( ' UTF-8 ' , ' utf-8 ' ) ] :
if termo in desc :
return enc
return None
def autodecode ( fonte ) :
if isinstance ( fonte , str ) :
enc = detectar_encoding ( fonte )
return fonte . decode ( enc ) if enc else fonte
else :
return fonte
>> >> >> > 3.1 . x
def dump_propriedades ( docs , path , salvar ) :
def dump_propriedades ( docs , path , salvar ) :
props_sapl = br ( docs [ ' props_sapl ' ] )
props_sapl = br ( docs [ ' props_sapl ' ] )
ids = [ p [ ' id ' ] for p in props_sapl [ ' _properties ' ] ]
ids = [ p [ ' id ' ] for p in props_sapl [ ' _properties ' ] ]
@ -335,9 +373,18 @@ def dump_usuarios(sapl, path, salvar):
save_as_yaml ( path , ' usuarios.yaml ' , users , salvar )
save_as_yaml ( path , ' usuarios.yaml ' , users , salvar )
<< << << < HEAD
def _dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar ) :
def _dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar ) :
assert Path ( data_fs_path ) . exists ( )
assert Path ( data_fs_path ) . exists ( )
assert Path ( documentos_fs_path ) . exists ( )
assert Path ( documentos_fs_path ) . exists ( )
== == == =
def _dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar , mtimes ) :
assert exists ( data_fs_path )
assert exists ( documentos_fs_path )
# precisamos trabalhar com strings e não Path's para as comparações de mtimes
data_fs_path , documentos_fs_path , destino = map ( str , (
data_fs_path , documentos_fs_path , destino ) )
>> >> >> > 3.1 . x
app , close_db = get_app ( data_fs_path )
app , close_db = get_app ( data_fs_path )
try :
try :
@ -352,12 +399,16 @@ def _dump_sapl(data_fs_path, documentos_fs_path, destino, salvar):
sapl = find_sapl ( app )
sapl = find_sapl ( app )
# extrai folhas XSLT
# extrai folhas XSLT
if ' XSLT ' in sapl :
if ' XSLT ' in sapl :
<< << << < HEAD
dump_folder ( br ( sapl [ ' XSLT ' ] ) , destino , salvar )
dump_folder ( br ( sapl [ ' XSLT ' ] ) , destino , salvar )
== == == =
dump_folder ( br ( sapl [ ' XSLT ' ] ) , destino , salvar , mtimes )
>> >> >> > 3.1 . x
# extrai documentos
# extrai documentos
docs = br ( sapl [ ' sapl_documentos ' ] )
docs = br ( sapl [ ' sapl_documentos ' ] )
with logando_nao_identificados ( ) :
with logando_nao_identificados ( ) :
dump_folder ( docs , destino , salvar )
dump_folder ( docs , destino , salvar , mtimes )
dump_propriedades ( docs , destino , salvar )
dump_propriedades ( docs , destino , salvar )
finally :
finally :
close_db ( )
close_db ( )
@ -367,32 +418,23 @@ def repo_execute(repo, cmd, *args):
return repo . git . execute ( cmd . split ( ) + list ( args ) )
return repo . git . execute ( cmd . split ( ) + list ( args ) )
def get_annex_hashes ( repo ) :
hashes = repo_execute (
repo , ' git annex find ' , ' --format=$ {keyname} \n ' , ' --include=* ' )
return { os . path . splitext ( h ) [ 0 ] for h in hashes . splitlines ( ) }
def ajusta_extensao ( fullname , conteudo ) :
def ajusta_extensao ( fullname , conteudo ) :
base , extensao = os . path . splitext ( fullname )
base , extensao = os . path . splitext ( fullname )
if extensao not in [ ' .xsl ' , ' .xslt ' , ' .yaml ' , ' .css ' ] :
if extensao not in [ ' .xsl ' , ' .xslt ' , ' .yaml ' , ' .css ' ] :
extensao = guess_extension ( fullname , conteudo )
extensao = guess_extension ( fullname , conteudo )
return base + extensao
return base + extensao , extensao
def build_salvar ( repo ) :
def build_salvar ( repo ) :
""" Constroi função salvar que pula arquivos que já estão no annex
"""
hashes = get_annex_hashes ( repo )
def salvar ( fullname , conteudo ) :
def salvar ( fullname , conteudo ) :
sha = hashlib . sha256 ( )
fullname , extensao = ajusta_extensao ( fullname , conteudo )
sha . update ( conteudo )
if sha . hexdigest ( ) in hashes :
# ajusta caminhos XSLT p conteúdos relacionados ao SDE
print ( ' - hash encontrado - {} ' . format ( fullname ) )
if extensao in [ ' .xsl ' , ' .xslt ' , ' .xml ' ] :
else :
conteudo = conteudo . replace ( ' " XSLT/HTML ' , ' " /XSLT/HTML ' )
fullname = ajusta_extensao ( fullname , conteudo )
if os . path . exists ( fullname ) :
if exists ( fullname ) :
# destrava arquivo pré-existente (o conteúdo mudou)
# destrava arquivo pré-existente (o conteúdo mudou)
repo_execute ( repo , ' git annex unlock ' , fullname )
repo_execute ( repo , ' git annex unlock ' , fullname )
with open ( fullname , ' w ' ) as arq :
with open ( fullname , ' w ' ) as arq :
@ -409,8 +451,13 @@ def dump_sapl(sigla):
' datafs ' , ' {} _cm_ {} .fs ' . format ( prefixo , sigla ) )
' datafs ' , ' {} _cm_ {} .fs ' . format ( prefixo , sigla ) )
for prefixo in ( ' Data ' , ' DocumentosSapl ' ) ]
for prefixo in ( ' Data ' , ' DocumentosSapl ' ) ]
<< << << < HEAD
assert data_fs_path . exists ( ) , ' Origem não existe: {} ' . format ( data_fs_path )
assert data_fs_path . exists ( ) , ' Origem não existe: {} ' . format ( data_fs_path )
if not documentos_fs_path . exists ( ) :
if not documentos_fs_path . exists ( ) :
== == == =
assert exists ( data_fs_path ) , ' Origem não existe: {} ' . format ( data_fs_path )
if not exists ( documentos_fs_path ) :
>> >> >> > 3.1 . x
documentos_fs_path = data_fs_path
documentos_fs_path = data_fs_path
nome_banco_legado = ' sapl_cm_ {} ' . format ( sigla )
nome_banco_legado = ' sapl_cm_ {} ' . format ( sigla )
@ -427,12 +474,21 @@ def dump_sapl(sigla):
salvar = build_salvar ( repo )
salvar = build_salvar ( repo )
try :
try :
finalizado = False
finalizado = False
<< << << < HEAD
_dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar )
_dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar )
== == == =
arq_mtimes = Path ( repo . working_dir , ' mtimes.yaml ' )
mtimes = yaml . load (
arq_mtimes . read_file ( ) ) if arq_mtimes . exists ( ) else { }
_dump_sapl ( data_fs_path , documentos_fs_path , destino , salvar , mtimes )
>> >> >> > 3.1 . x
finalizado = True
finalizado = True
finally :
finally :
# grava mundaças
# grava mundaças
repo_execute ( repo , ' git annex add sapl_documentos ' )
repo_execute ( repo , ' git annex add sapl_documentos ' )
arq_mtimes . write_file ( yaml . safe_dump ( mtimes , allow_unicode = True ) )
repo . git . add ( A = True )
repo . git . add ( A = True )
# atualiza repo
if ' master ' not in repo . heads or repo . index . diff ( ' HEAD ' ) :
if ' master ' not in repo . heads or repo . index . diff ( ' HEAD ' ) :
# se de fato existe mudança
# se de fato existe mudança
status = ' completa ' if finalizado else ' parcial '
status = ' completa ' if finalizado else ' parcial '