
'-----------------------------------------------------------------------------------------------------
' Скрипт предназначен для автоматизации процесса объединения своих изменений конфигурации
' с основным МДшником. Предполагается следующая технология объединения:
' 1) Взять последнюю версию МДшника (например из VSS)
' 2) Загрузить этот МДшник в пустую базу, служащую только для слияния МДшников.
' 3) Запустить процесс объединения с МДшником, в котором сделаны изменени
' 4) Поставить нужные галки, и объединить МДшники
' 5) Записать обновлённую версию МДшника в систему контроля версий. Или скопировать куда-нибудь.
'
' Данный скрипт позволяет автоматизировать шаги 1, 2, 3 и 5.
' Все пути к файлам и всякие параметры прописываются в файле MD_Tasks.ini, который должен лежать в каталоге ИБ.
' Параметры могут быть такими:
'	LatestVersion = X:\1C_Bases\1cv7.md
'	Changes = Z:\1C_Bases\Бух-Тестовая\1cv7.md
'	VSS_Path = $/1c/Бухгалтерия/current/1cv7.md
'	CVS_Path = Z:\1C_Bases\Бух-Тестовая\SRC
'	RunWinCVSAfterDecompile = yes/no
'	CheckOut = Yes
'	ExternalMerge = kdiff3
'	StartUpScript = LoadAndMergeMD
'
' Строки, начинающиеся с символа ';' считаются комментариями.
' Параметры 'LatestVersion' и 'Changes' являются обязательными.
'
' Если задан параметр 'VSS_Path', то перед загрузкой МДшника скрипт попытается взять последнюю
' версию из VSS, и положить в файл 'LatestVersion'.
' Если задан 'CheckOut', то будет выполнена команда 'ss checkout' вместо 'ss get'.
'
' Если задан параметр CVS_Path (путь к рабочему каталогу CVS), то считается, что конфигурация
' хранится в CVS, в разобранном виде.
'
' Если задан 'ExternalMerge', то слияние изменений будет выполняться указанной внешней программой с последующей загрузкой МДшника 'Changes'.
' Если задан 'StartUpScript', то он выполнится при старте конфигуратора.
'
' Если файла MD_Tasks.ini нет в каталоге ИБ, то скрипт выгружается.
'
'Версия: $Revision: 1.6 $ 
'-----------------------------------------------------------------------------------------------------



Dim INI_FileName
Dim MD_Path
Dim LatestVersion_MD
Dim Changes_MD
Dim Current_MD
Dim VSS_Path, CheckOut, SS_Command
Dim CVS_Path, CVS_Command, WinCVS_Command, GComp_Command
Dim RunWinCVSAfterDecompile
Dim ExternalDiffCommand
Dim ERTDecompileOptions
Dim StartUpScript
Dim Mode

Dim fso
Dim CM_CLOSE


'======== Init ===================================================
MD_Path = ""
INI_FileName = IBDir & "MD_Tasks.ini"
Current_MD = IBDir & "1cv7.md"
SS_Command = """C:\Program Files\Microsoft Visual Studio\VSS\win32\ss.exe"""
CVS_Command = "cvs.exe "
'WinCVS_Command = """C:\Program Files\GNU\WinCvs 1.3\wincvs.exe"" "
WinCVS_Command = """C:\Program Files\GNU\WinCvs 1.3\WinCVS.exe"" "
RunWinCVSAfterDecompile = true
GComp_Command = "gcomp.exe "
CheckOut = false
ExternalDiffCommand = "kdiff3.exe"
ERTDecompileOptions = "-v --no-ini --no-version --no-empty-mxl"
ReadSettings 0

If StartUpScript <> "" Then
	Message "Run '" & StartUpScript & "'", mBlueTriangle
	Execute "Call " & StartUpScript
End If

Set fso = CreateObject("Scripting.FileSystemObject")
CM_CLOSE = 57602
'=================================================================

'Забираем последнюю версию из CVS
Function GetFromCVS()
	GetFromCVS = true
	
	If Not GetERTDoc Is Nothing Then
		UpdateCurrentErtFromCVS
		Exit Function
	End If

	
	If CVS_Path = "" Then
		GetFromCVS = false
		Exit Function
	End If
	
	GetFromCVS = true
	
	If fso.FileExists(LatestVersion_MD) Then
		fso.DeleteFile LatestVersion_MD, true
	End If

	RunCommand CVS_Command & " -z9 -q update -d -P ", """" & CVS_Path & """"
	CmdLine = GComp_Command & " -c -F """ & LatestVersion_MD & """ -DD """ & CVS_Path & """"
	RunCommand CmdLine, IBDir

	If fso.FileExists(LatestVersion_MD) Then
		Message "Module '" & CVS_Path & "' loaded from CVS into  '" & LatestVersion_MD & "'", mInformation
	Else
		Message "Can not load module '" & CVS_Path & "' from CVS", mExclamation
		GetFromCVS = false
	End If
End Function

'разобрать и запустить WinCVS
Sub PutOnCVS()
	If GetERTDoc Is Nothing Then
		CmdLine = "decompile.bat"
		RunCommand "decompile.bat", IBDir

		if RunWinCVSAfterDecompile then StartWinCVS CVS_Path
	Else
		DecompileCurrentErt
	End If
End Sub

'Загрузить последнюю версию
Sub LoadCurrentVersion()
	If CheckFile(LatestVersion_MD) = 0 Then Exit Sub

	CloseWindows 0
	Message "Load " & LatestVersion_MD, mInformation
	Mode = 1
	MD_Path = LatestVersion_MD
	SendCommand cmdLoadMD
End Sub

'Запустить объединение
Sub MergeCurrentMD()
	If LatestVersion_MD = "" Then
		Mode = 0
		MD_Path = ""
		Exit Sub
	End If
	
	If CheckFile(LatestVersion_MD) = 0 Then Exit Sub

	Message "Merge with " & LatestVersion_MD, mInformation

	If ExternalDiffCommand <> "" Then
		ExternalDiff 0
	Else
		Mode = 2
		MD_Path = LatestVersion_MD
		SendCommand cmdMergeMD
	End If
End Sub

Sub OpenINI()
	Documents.Open INI_FileName
End Sub



'================================================================
Private Function GetERTDoc()
	Set GetERTDoc = Nothing
    If Windows.ActiveWnd Is Nothing Then Exit Function
    If Windows.ActiveWnd.Document <> docWorkBook Then Exit Function
    Dim Doc ' As WorkBook
    Set Doc = Windows.ActiveWnd.Document
    If Doc.ID > 0 Then Exit Function
    
    Set GetERTDoc = Doc
End Function


'================================================================
'Декомпиляция текущего внешнего отчёта
Private Sub DecompileCurrentErt()
	Set Doc = GetERTDoc

	If Doc Is Nothing Then MsgBox "Это не внешний отчет", ,SelfScript.Name: Exit Sub
	If Len(Doc.Path) = 0 Then MsgBox "Файл не записан", , SelfScript.Name: Exit Sub

	Path = LCase(Doc.Path)
	If InStr(Path, LCase(IBDir)) <> 1 Then
		MsgBox "Процедура работает только с отчетами в каталоге ИБ", , SelfScript.Name
		Exit Sub
	End If

	Doc.Save

	Path = Doc.Path
	FolderName = fso.GetParentFolderName(Path)
	ERTName = fso.GetBaseName(Path)
	DestDir = fso.BuildPath(FolderName, ERTName)


	CmdLine = GComp_Command & " -d -F """ & Path & """ -DD """ & DestDir & """ " & ERTDecompileOptions
	RunCommand CmdLine, FolderName
	
	if RunWinCVSAfterDecompile then StartWinCVS FolderName
End Sub

'================================================================
'Ккомпиляция текущего внешнего отчёта
Private Sub UpdateCurrentErtFromCVS()
	Set Doc = GetERTDoc

	If Doc Is Nothing Then MsgBox "Это не внешний отчет", ,SelfScript.Name: Exit Sub

	Path = LCase(Doc.Path)
	
	If Len(Path) = 0 Then MsgBox "Файл не записан", , SelfScript.Name: Exit Sub
	
	If InStr(Path, LCase(IBDir)) <> 1 Then
		MsgBox "Процедура работает только с отчетами в каталоге ИБ", , SelfScript.Name
		Exit Sub
	End If

	Path = Doc.Path
	FolderName = fso.GetParentFolderName(Path)
	ERTName = fso.GetBaseName(Path)
	DestDir = fso.BuildPath(FolderName, ERTName)

	'Doc.Save
	'DecompileCurrentERT

	'Close current ert
	SendCommand(CM_CLOSE)
	

	'Update from CVS
	CmdLine = CVS_Command & " -z9 -q update -d "
	RunCommand CmdLine, DestDir
	
	'Compile ert
	CmdLine = GComp_Command & " -c -F """ & Path & """ -DD """ & DestDir & """"
	RunCommand CmdLine, FolderName

	'Open compiled ert
	Set Doc = Documents.Open(Path)
End Sub



Function StrToBool(ByVal str)
	StrToBool = false
	str = Trim(LCase(str))
	If str = "1" or str = "yes" or str = "да" Then StrToBool = true
End Function

'Читаем настройки из ini-файла
Sub ReadSettings(param)
	Set fso = CreateObject("Scripting.FileSystemObject")
	If not fso.FileExists(INI_FileName) Then
		'Message "File " & INI_FileName & " not found", mExclamation
		'Раз нет ini-файла, то скрипт нам не нужен, и мы его выгрузим
		Scripts.Unload SelfScript.Name
		Exit Sub
	End If

	Set ini_file = fso.OpenTextFile(INI_FileName, 1, False)
	Set RE = New RegExp
	RE.Pattern = "(\w+)\s*=\s*(.*)"
	Do While not ini_file.AtEndOfStream
		line = Trim(ini_file.ReadLine)
		If Left(line, 1) <> ";" Then
			Set Matches = RE.Execute(line)
			If Matches.Count > 0 Then
				ParamName = Matches(0).Submatches(0)
				ParamVal = Trim(Matches(0).Submatches(1))
				If ParamName = "LatestVersion" Then
					LatestVersion_MD = Trim(ParamVal)
					If LatestVersion_MD = "" Then LatestVersion_MD = IBDir & "1cv7.new.md"
				ElseIf ParamName = "Changes" Then
					Changes_MD = ParamVal
				ElseIf ParamName = "CVS_Path" Then
					CVS_Path = Trim(ParamVal)
					If CVS_Path = "" Then CVS_Path = IBDir & "Src"
				ElseIf ParamName = "VSS_Path" Then
					VSS_Path = ParamVal
				ElseIf ParamName = "CheckOut" Then
					CheckOut = StrToBool(ParamVal)
				ElseIf ParamName = "StartUpScript" Then
					StartUpScript = ParamVal
				ElseIf ParamName = "ExternalDiff" Then
					ExternalDiffCommand = ParamVal
				ElseIf ParamName = "RunWinCVSAfterDecompile" Then
					If LCase(ParamVal) = "yes" or LCase(ParamVal) = "да" Then
						RunWinCVSAfterDecompile = true
					Else
						RunWinCVSAfterDecompile = false
					End If
				End If
			End If
		End If
	Loop
	ini_file.Close
	
	If CVS_Path <> "" Then
		VSS_Path = ""
		Changes = ""
	End If
End Sub

'Закрываем все окна, какие уже наоткрывались
Sub CloseWindows(param)
	While Not Windows.ActiveWnd Is Nothing
		Windows.ActiveWnd.Close
	Wend
End Sub

'Проверяем наличие файла и заодно сбрасываем флаг ReadOnly
Function CheckFile(FName)
	CheckFile = true
	Set fso = CreateObject("Scripting.FileSystemObject")
	If not fso.FileExists(FName) Then
		Message "File " & FName & " not exist", mExclamation
		CheckFile = false
	Else
		Set file = fso.GetFile(FName)
		file.Attributes = 0 'turn off ReadOnly flag
	End If
End Function

'================================================================
Sub RunCommand(CmdLine, WorkDir)
	set wshShell = createObject("WScript.Shell")
	If WorkDir <> "" Then wshShell.CurrentDirectory =  WorkDir
	Message CmdLine, mBlueTriangle
	res = wshShell.Run(CmdLine, 1, true)
	'Message "" & res, mNone
	'Set job = wshShell.Exec(CmdLine)
	'Message "" & job.Status
	'do while not job.StdOut.AtEndOfStream
	'	Message job.StdOut.ReadLine(), mNone
	'loop
	''outputLines = job.StdOut.ReadAll()
End Sub

'================================================================
Sub StartWinCVS(Path)
	set wshShell = createObject("WScript.Shell")
	CmdLine = WinCVS_Command & " """ & Path & "\"""
	'Message CmdLine
	res = wshShell.Run(CmdLine, 1, false)
End Sub




Sub ExternalDiff(param)
	OldDir = IBDir & "Src_Old"
	NewDir = IBDir & "Src_New"
	RunCommand GComp_Command & " -d -F """ & Current_MD & """  -D """ & OldDir & """", ""
	RunCommand GComp_Command & " -d -F """ & Changes_MD & """  -D """ & NewDir & """", ""
	RunCommand """" & ExternalDiffCommand & """ """ & OldDir & """ """ & NewDir & """", ""

	answer = MsgBox("Загрузить изменённый МД?", vbYesNo)
	If answer = vbYes Then
		RunCommand GComp_Command & " -c -F """ & LatestVersion_MD & """  -D """ & NewDir & """", ""
		LoadChangedMD
	End If
End Sub

Sub Configurator_OnFileDialog(Saved, Caption, Filter, FileName, Answer)
	'После команды на загрузку МД 1С запросит имя файла.
	'Message "MD_Path = '" & MD_Path & "'"
	If Saved Then Exit Sub
	If MD_Path <> "" Then
		FileName = MD_Path
		Answer = mbaOK

		If Mode = 2 Then MD_Path = ""
	End If
End Sub

Sub Configurator_ConfigWindowCreate()
	'Раз окно открылось, значит все загрузилось, надо сохранить конфигурацию
	If MD_Path <> "" Then
		SendCommand cmdSave
	End If
End Sub


Sub Configurator_OnMsgBox(Text, Style, DefAnswer, Answer)
	If MD_Path <> "" Then
		Answer = DefAnswer
		Message Text, mExclamation 'выдадим в окно сообщений текст модального окна
		Text = Trim(LCase(Text))
		If InStr(Text, "файл") <> 0 And InStr(Text, "не найден") <> 0 Then
			MD_Path = ""
			Mode = 0
			'Answer = 0 'оставим окно висеть
		ElseIf InStr(Text, "ошибка разделения данных при доступе к") <> 0 Then
			MD_Path = ""
			Mode = 0
			'Answer = 0 'оставим окно висеть
		ElseIf Text = "реорганизация информации закончена!" Then
			If Mode = 3 Then
				MergeWithDevelopersMD
			Else
				MD_Path = "" 'всё, больше нам не нужно реагировать на окна
			End If
		End If
	Else
		Mode = 0
	End If
End Sub

Sub Configurator_OnDoModal(Hwnd, Caption, Answer)
	If MD_Path <> "" Then
		Message Caption, mInformation
		Answer = mbaOK
	Else
		Mode = 0
	End If
End Sub

