Compare commits
137 Commits
release/20
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aff6e71cf6 | ||
|
|
0e663748db | ||
|
|
566f300967 | ||
|
|
2d02ac093b | ||
|
|
8c98a3f38f | ||
|
|
b8f206f1d4 | ||
|
|
69e2ca5ce6 | ||
|
|
1020303fec | ||
|
|
68dee3f3a4 | ||
|
|
64f3f534a2 | ||
|
|
4588c2f1e8 | ||
|
|
5eb7dd3ef7 | ||
|
|
c548c55274 | ||
|
|
fcc7af9991 | ||
|
|
e79bb4f8be | ||
|
|
e8d25cd78f | ||
|
|
55408ffda6 | ||
|
|
803e6ef418 | ||
|
|
0b831773af | ||
|
|
bc4bd61de6 | ||
|
|
38426b8a64 | ||
|
|
e9ebb418f3 | ||
|
|
f2cbb733a0 | ||
|
|
195f123c05 | ||
|
|
3408da4f40 | ||
|
|
ab34ede1ea | ||
|
|
dddf9dcb83 | ||
|
|
f6cbce7324 | ||
|
|
6034143788 | ||
|
|
7ad60c4471 | ||
|
|
4f5fd4bea6 | ||
|
|
2ab43e6c0a | ||
|
|
663eaaa65b | ||
|
|
e950c89c2f | ||
|
|
bcb4eb6064 | ||
|
|
c1a00bb944 | ||
|
|
480f8bbb68 | ||
|
|
f1e8e8b4a2 | ||
|
|
4f4a2c9cdd | ||
|
|
dd510b0286 | ||
|
|
018f0907c2 | ||
|
|
f2a27e592d | ||
|
|
89d526e740 | ||
|
|
68e2df9db6 | ||
|
|
87c11e7e2f | ||
|
|
7142621966 | ||
|
|
54d6196698 | ||
|
|
6b970f8e02 | ||
|
|
fb28f40b72 | ||
|
|
efd4f15d9d | ||
|
|
be74bb8017 | ||
|
|
3acff3caba | ||
|
|
c6eb59eb42 | ||
|
|
89948603de | ||
|
|
25a9835014 | ||
|
|
70eb74bc09 | ||
|
|
3e3b63181b | ||
|
|
91ea5ba877 | ||
|
|
b2754b573a | ||
|
|
6029b13828 | ||
|
|
6e8acf6fdc | ||
|
|
f16831a51d | ||
|
|
117fffef0b | ||
|
|
47570b3676 | ||
|
|
250152fd7c | ||
|
|
7dbf960291 | ||
|
|
5fa23309c5 | ||
|
|
e8fb2f58f2 | ||
|
|
5bf2814178 | ||
|
|
b621bbe3e8 | ||
|
|
9c41bca63f | ||
|
|
efab6d7e51 | ||
|
|
910e3ec490 | ||
|
|
df6d8be57f | ||
|
|
b670f096be | ||
|
|
b7d27d156f | ||
|
|
51e37ac662 | ||
|
|
1d68e73690 | ||
|
|
aeaf259c59 | ||
|
|
257ba0f733 | ||
|
|
7eb3a8886f | ||
|
|
e86954cc7f | ||
|
|
f23197f811 | ||
|
|
f28db85017 | ||
|
|
3f85e1911e | ||
|
|
b350cd9827 | ||
|
|
8e22064b71 | ||
|
|
7a64df78e3 | ||
|
|
493ad2c306 | ||
|
|
533cec6236 | ||
|
|
0dd0bf3043 | ||
|
|
b0594ed4ef | ||
|
|
f2e86108d4 | ||
|
|
8462f3217a | ||
|
|
735f5160e4 | ||
|
|
a5949431b1 | ||
|
|
0622410e4a | ||
|
|
acb8a7a793 | ||
|
|
93b71e29e6 | ||
|
|
fcf5087da9 | ||
|
|
2c7e8318db | ||
|
|
157ce05c69 | ||
|
|
799b0b4ad6 | ||
|
|
c9f7483fc4 | ||
|
|
4d3a5fb528 | ||
|
|
e8a6c477cc | ||
|
|
21a53b3537 | ||
|
|
37ff25cfe4 | ||
|
|
0409f339ae | ||
|
|
771c2a2abe | ||
|
|
224a9a0b18 | ||
|
|
08cb5c481b | ||
|
|
c23ec2827f | ||
|
|
ba8feb7d6f | ||
|
|
f1f612206f | ||
|
|
ef36d50d9b | ||
|
|
5b969d37ec | ||
|
|
8e82d4e1fb | ||
|
|
2dfbc989ba | ||
|
|
93b085f441 | ||
|
|
52bceabab7 | ||
|
|
cee226183c | ||
|
|
6cb7d12ec1 | ||
|
|
16a42dfc6b | ||
|
|
9d6ce08430 | ||
|
|
95b7ef534b | ||
|
|
b03d12313a | ||
|
|
13137727b0 | ||
|
|
7e30b2f87a | ||
|
|
6a356f7e18 | ||
|
|
b2743b92f3 | ||
|
|
f57a5ed4cb | ||
|
|
249f00dd32 | ||
|
|
f581b93d9b | ||
|
|
2a1b666a5e | ||
|
|
92864a4c1a | ||
|
|
03ef344ada |
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
.gitattributes text export-ignore
|
||||
.gitignore text export-ignore
|
||||
*.py text
|
||||
*.txt text
|
||||
*.rst text
|
||||
*.xml text
|
||||
*.desktop text
|
||||
*.svg text
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.bat text eol=crlf
|
||||
AUTHORS text
|
||||
COPYING text
|
||||
COPYING.* text
|
||||
README.* text
|
||||
Makefile text
|
||||
ChangeLog text
|
||||
ChangeLog.* text
|
||||
/download_and_compile.sh text ident
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -20,3 +20,5 @@ archivebuild
|
||||
osgbuild
|
||||
CMakeCache.txt
|
||||
*.pyc
|
||||
build-*
|
||||
testOutput*
|
||||
|
||||
20
.gitmodules
vendored
20
.gitmodules
vendored
@@ -1,20 +1,24 @@
|
||||
[submodule "simgear"]
|
||||
path = simgear
|
||||
url = git://git.code.sf.net/p/flightgear/simgear
|
||||
branch = next
|
||||
url = ../simgear
|
||||
branch = release/2018.2
|
||||
[submodule "flightgear"]
|
||||
path = flightgear
|
||||
url = git://git.code.sf.net/p/flightgear/flightgear
|
||||
branch = next
|
||||
url = ../flightgear
|
||||
branch = release/2018.2
|
||||
[submodule "fgrun"]
|
||||
path = fgrun
|
||||
url = git://git.code.sf.net/p/flightgear/fgrun
|
||||
url = ../fgrun
|
||||
branch = next
|
||||
[submodule "fgdata"]
|
||||
path = fgdata
|
||||
url = git://git.code.sf.net/p/flightgear/fgdata
|
||||
branch = next
|
||||
url = ../fgdata
|
||||
branch = release/2018.2
|
||||
[submodule "windows-3rd-party"]
|
||||
path = windows-3rd-party
|
||||
url = git://git.code.sf.net/p/flightgear/windows-3rd-party
|
||||
url = ../windows-3rd-party
|
||||
branch = master
|
||||
[submodule "getstart"]
|
||||
path = getstart
|
||||
url = ../getstart
|
||||
branch = release/2018.2
|
||||
|
||||
116
FlightGear.iss
116
FlightGear.iss
@@ -16,17 +16,10 @@
|
||||
;
|
||||
; C:\> subst X: F:\Path\to\FlightGear\root
|
||||
; C:\> subst X: F:\
|
||||
;
|
||||
;
|
||||
|
||||
#include "InstallConfig.iss"
|
||||
|
||||
#if GetEnv("VSINSTALLDIR") == ""
|
||||
#define VSInstallDir "C:\Program Files (x86)\Microsoft Visual Studio 14.0"
|
||||
#else
|
||||
#define VSInstallDir GetEnv("VSINSTALLDIR")
|
||||
#endif
|
||||
|
||||
#define VCInstallDir VSInstallDir + "\VC"
|
||||
#define InstallDir32 "X:\install\msvc140"
|
||||
#define OSGInstallDir InstallDir32 + "\OpenSceneGraph"
|
||||
#define OSGPluginsDir OSGInstallDir + "\bin\osgPlugins-" + OSGVersion
|
||||
@@ -69,12 +62,11 @@ ArchitecturesAllowed=x86 x64
|
||||
|
||||
; Sign tool must be defined in the Inno Setup GUI, to avoid
|
||||
; exposing the certificate password
|
||||
; SignTool=fg_code_sign1
|
||||
; SignTool=fg_code_sign1
|
||||
|
||||
[Tasks]
|
||||
; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
|
||||
Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"
|
||||
;Name: "insoal"; Description: "Install OpenAL (the sound engine)"
|
||||
|
||||
[Files]
|
||||
; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at)
|
||||
@@ -82,36 +74,31 @@ Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "A
|
||||
; 32 bits install
|
||||
|
||||
Source: "{#InstallDir32}\bin\*.*"; DestDir: "{app}\bin"; Excludes: "{#ExcludedBinaries}"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode
|
||||
Source: "{#InstallDir32}\share\locale\*"; DestDir: "{app}\bin\locale"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode
|
||||
;locale only exists for fgrun - which has been disabled
|
||||
;Source: "{#InstallDir32}\share\locale\*"; DestDir: "{app}\bin\locale"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode
|
||||
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\zlib.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\OpenAL32.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\libpng.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\libcurl.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\libintl-8.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
;Source: "X:\3rdParty\bin\CrashRpt1402.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
;Source: "X:\3rdParty\bin\crashrpt_lang.ini"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
;Source: "X:\3rdParty\bin\CrashSender1402.exe"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#VCInstallDir}\redist\x86\Microsoft.VC140.CRT\*.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\CrashRpt1403.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\crashrpt_lang.ini"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty\bin\CrashSender1403.exe"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
|
||||
; 64 bits install
|
||||
Source: "{#InstallDir64}\bin\*.*"; DestDir: "{app}\bin"; Excludes: "{#ExcludedBinaries}"; Flags: ignoreversion recursesubdirs; Check: Is64BitInstallMode
|
||||
Source: "{#InstallDir64}\share\locale\*"; DestDir: "{app}\bin\locale"; Flags: ignoreversion recursesubdirs; Check: Is64BitInstallMode
|
||||
;locale only exists for fgrun - which has been disabled
|
||||
;Source: "{#InstallDir64}\share\locale\*"; DestDir: "{app}\bin\locale"; Flags: ignoreversion recursesubdirs; Check: Is64BitInstallMode
|
||||
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\zlib.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\OpenAL32.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\libpng.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\libcurl.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\libintl-8.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
;Source: "X:\3rdParty.x64\bin\CrashRpt1402.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
;Source: "X:\3rdParty.x64\bin\crashrpt_lang.ini"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
;Source: "X:\3rdParty.x64\bin\CrashSender1402.exe"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#VCInstallDir}\redist\x64\Microsoft.VC140.CRT\*.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
|
||||
; 32/64 bits install
|
||||
;NOTE: FGPanel has no 64 bits equivalent, so we are using the 32 bits binary for 32&64 bits OS
|
||||
Source: "{#InstallDir32}\bin\fgpanel.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
;Source: "X:\3rdParty\bin\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion skipifsourcedoesntexist
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\CrashRpt1403.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\crashrpt_lang.ini"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#ThirdPartyDir}\3rdParty.x64\bin\CrashSender1403.exe"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
|
||||
; Include the base package
|
||||
#if IncludeData == "TRUE"
|
||||
@@ -202,11 +189,10 @@ Name: "{userdocs}\FlightGear\Custom Scenery"; Permissions: everyone-modify; Chec
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\FlightGear {#FGVersion}"; Filename: "{app}\bin\fgfs.exe"; Parameters: "--launcher"; WorkingDir: "{app}\bin"; Tasks: desktopicon;
|
||||
Name: "{group}\FlightGear Launcher"; Filename: "{app}\bin\fgfs.exe"; Parameters: "--launcher"; WorkingDir: "{app}\bin";
|
||||
Name: "{group}\FlightGear"; Filename: "{app}\bin\fgfs.exe"; Parameters: "--launcher"; WorkingDir: "{app}\bin";
|
||||
Name: "{group}\FlightGear Manual"; Filename: "{app}\data\Docs\getstart.pdf"
|
||||
Name: "{group}\FlightGear Documentation"; Filename: "{app}\data\Docs\index.html"
|
||||
Name: "{group}\Flightgear Wiki"; Filename: "http://wiki.flightgear.org"
|
||||
Name: "{group}\Tools\FGRun"; Filename: "{app}\bin\fgrun.exe"; WorkingDir: "{app}";
|
||||
Name: "{group}\Tools\Uninstall FlightGear"; Filename: "{uninstallexe}"
|
||||
Name: "{group}\Tools\fgjs"; Filename: "cmd"; Parameters: "/k fgjs.exe ""--fg-root={app}\data"""; WorkingDir: "{app}\bin"
|
||||
Name: "{group}\Tools\yasim"; Filename: "cmd"; Parameters: "/k ""{app}\bin\yasim.exe"" -h"; WorkingDir: "{app}\bin"
|
||||
@@ -215,11 +201,6 @@ Name: "{group}\Tools\FGCom"; Filename: "{app}\bin\fgcom.exe"; WorkingDir: "{app}
|
||||
Name: "{group}\Tools\FGCom-testing"; Filename: "{app}\bin\fgcom.exe"; Parameters: "--frequency=910"; WorkingDir: "{app}\bin"
|
||||
Name: "{group}\Tools\Explore Documentation Folder"; Filename: "{app}\data\Docs"
|
||||
|
||||
[Run]
|
||||
; filename: "{app}\bin\oalinst.exe"; WorkingDir: "{app}\bin"; Description: "Installing OpenAL"; Check: IsTaskSelected('insoal') and FileExists(ExpandConstant('{app}\bin\oalinst.exe'))
|
||||
; Put installation directory into the fgrun.prefs
|
||||
filename: "{app}\bin\fgrun.exe"; WorkingDir: "{app}\bin"; Parameters: "--silent ""--fg-exe={app}\bin\fgfs.exe"" ""--fg-root={app}\data"" ""--fg-scenery={userdocs}\FlightGear\Custom Scenery;{app}\data\Scenery;{userdocs}\FlightGear\TerraSync"" ""--fg-aircraft={userdocs}\FlightGear\Aircraft"" ""--terrasync-dir={userdocs}\FlightGear\TerraSync"" --version={#FGVersion}"
|
||||
|
||||
[Code]
|
||||
const
|
||||
NET_FW_SCOPE_ALL = 0;
|
||||
@@ -338,6 +319,66 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
UninstallCheckCleanPage: TNewNotebookPage;
|
||||
UninstallBackButton: TNewButton;
|
||||
UninstallNextButton: TNewButton;
|
||||
DoCleanCheckbox : TNewCheckBox;
|
||||
CleanHelp : TNewStaticText;
|
||||
|
||||
procedure InitializeUninstallProgressForm();
|
||||
begin
|
||||
UninstallProgressForm
|
||||
|
||||
UninstallCheckCleanPage := TNewNotebookPage.Create(UninstallProgressForm);
|
||||
UninstallCheckCleanPage.Notebook := UninstallProgressForm.InnerNotebook;
|
||||
UninstallCheckCleanPage.Parent := UninstallProgressForm.InnerNotebook;
|
||||
UninstallCheckCleanPage.Align := alClient
|
||||
|
||||
DoCleanCheckbox := TNewCheckBox.Create(UninstallProgressForm);
|
||||
DoCleanCheckbox.Parent := UninstallCheckCleanPage;
|
||||
DoCleanCheckbox.Caption := 'Remove all settings, downloaded scenery and aircraft';
|
||||
DoCleanCheckbox.Left := ScaleX(10);
|
||||
DoCleanCheckbox.Top := ScaleY(10);
|
||||
|
||||
DoCleanCheckbox.Width := UninstallProgressForm.InnerNotebook.Width - ScaleX(20)
|
||||
DoCleanCheckbox.Height := ScaleY(30)
|
||||
|
||||
CleanHelp := TNewStaticText.Create(UninstallProgressForm);
|
||||
CleanHelp.Parent := UninstallCheckCleanPage;
|
||||
CleanHelp.Top := DoCleanCheckbox.Top + DoCleanCheckbox.Height + ScaleY(10);
|
||||
CleanHelp.Left := DoCleanCheckbox.Left;
|
||||
CleanHelp.Width := DoCleanCheckbox.Width;
|
||||
CleanHelp.Height := CleanHelp.AdjustHeight();
|
||||
|
||||
CleanHelp.WordWrap := True;
|
||||
CleanHelp.Caption := 'FlightGear stores some settings in your user folder. In addition, ' +
|
||||
'scenery or aircraft data may have been downloaded to the download directory. ' +
|
||||
'To completely remove all these files, select this option.';
|
||||
|
||||
UninstallProgressForm.InnerNotebook.ActivePage := UninstallCheckCleanPage;
|
||||
|
||||
UninstallNextButton := TNewButton.Create(UninstallProgressForm);
|
||||
UninstallNextButton.Caption := 'Next';
|
||||
UninstallNextButton.Parent := UninstallProgressForm;
|
||||
UninstallNextButton.Left :=
|
||||
UninstallProgressForm.CancelButton.Left -
|
||||
UninstallProgressForm.CancelButton.Width -
|
||||
ScaleX(10);
|
||||
UninstallNextButton.Top := UninstallProgressForm.CancelButton.Top;
|
||||
UninstallNextButton.Width := UninstallProgressForm.CancelButton.Width;
|
||||
UninstallNextButton.Height := UninstallProgressForm.CancelButton.Height;
|
||||
UninstallNextButton.ModalResult := mrOk;
|
||||
|
||||
UninstallProgressForm.CancelButton.Enabled := True;
|
||||
UninstallProgressForm.CancelButton.ModalResult := mrCancel;
|
||||
|
||||
if UninstallProgressForm.ShowModal = mrCancel then Abort;
|
||||
|
||||
UninstallProgressForm.InnerNotebook.ActivePage := UninstallProgressForm.InstallingPage;
|
||||
end;
|
||||
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
Version: TWindowsVersion;
|
||||
@@ -363,7 +404,18 @@ begin
|
||||
end;
|
||||
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
var ResultCode: Integer;
|
||||
begin
|
||||
if CurUninstallStep = usUninstall then
|
||||
begin
|
||||
if DoCleanCheckbox.Checked = True then
|
||||
begin
|
||||
Log('Running clean uninstall');
|
||||
Exec(ExpandConstant('{app}\bin\fgfs.exe'), '--uninstall', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
Log('clean uninstall completed');
|
||||
end;
|
||||
end;
|
||||
|
||||
if CurUninstallStep = usPostUninstall then
|
||||
begin
|
||||
RemoveFirewallException('FlightGear', ExpandConstant('{app}') + '\bin\fgfs.exe');
|
||||
|
||||
339
Nasa2FGearthview/LICENSE
Normal file
339
Nasa2FGearthview/LICENSE
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
167
Nasa2FGearthview/README.md
Normal file
167
Nasa2FGearthview/README.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Nasa2FGearthview
|
||||
A bash-script to convert NASA satellite images to ready-to-use
|
||||
textures for FG's EarthView using ImageMagick.
|
||||
|
||||
For info about FGearthview, see the forum thread:
|
||||
https://forum.flightgear.org/viewtopic.php?f=6&t=15754
|
||||
or this FG-wiki-page:
|
||||
http://wiki.flightgear.org/Earthview
|
||||
|
||||
|
||||
------------------------------------
|
||||
About:
|
||||
|
||||
This script runs on Linux (maybe Mac also?) in a Bash
|
||||
(Bourne Again Shell) - Windows is not supported (by the nature of the
|
||||
script). Maybe it works on windows as well, I don't know, feel free
|
||||
to try, and please let me know! :)
|
||||
|
||||
This will download the raw images from http://visibleearth.nasa.gov -
|
||||
their server is not very fast, so I provide an alternative download
|
||||
location: https://musicchris.de/download/FG/EarthView/raw-data-NASA.7z
|
||||
This one is much quicker! If you really want the images directly from
|
||||
NASA, then provide "nasa" to the script (see below)
|
||||
|
||||
In the end you will have 8 world-textures in .png and .dds format.
|
||||
Generally .dds is better in performance, but it won't work on some
|
||||
graphics cards. If this is the case for you, then try the .png files.
|
||||
For further information see:
|
||||
http://wiki.flightgear.org/index.php?title=DDS_Textures_in_FlightGear&redirect=no
|
||||
|
||||
If you also converted the clouds, then you'll also find 8 cloud-
|
||||
textures in the format .png. Because the .dds-format has trouble with
|
||||
rendering heavy alpha images, which is because of it's compression
|
||||
algorythm [1], I think it's useless to also build faulty files.
|
||||
However, this is not entirely true! It is possible to switch off the
|
||||
.dds/DXT compression. But this results in huge files and is rather
|
||||
heavy on the GPU's RAM.
|
||||
|
||||
Buckaroo has created a nice overview on dds-compression:
|
||||
[1] http://www.buckarooshangar.com/flightgear/tut_dds.html
|
||||
|
||||
------------------------------------
|
||||
Installation and usage:
|
||||
|
||||
Simply copy "convert.sh" into a folder of your liking and run it:
|
||||
|
||||
$ ./convert.sh
|
||||
|
||||
This will show a help text, since you didn't specify any target(s).
|
||||
Possible targets are:
|
||||
* world
|
||||
* clouds
|
||||
* all
|
||||
|
||||
Additionally, there are some options you could specify (further
|
||||
explained below):
|
||||
* 1k | 2k | 4k | 8k | 16k
|
||||
* nasa
|
||||
* no-download
|
||||
* cleanup
|
||||
* rebuild
|
||||
* check
|
||||
|
||||
So your call could look sth like this:
|
||||
|
||||
$ ./convert.sh world no-download cleanup 8k
|
||||
|
||||
|
||||
------------------------------------
|
||||
Requirements:
|
||||
|
||||
WARNING!
|
||||
|
||||
This script uses a *lot* disk space! Make sure you have at least 90GB
|
||||
available!
|
||||
|
||||
Also, this script will run for a *very long* time! It might be best to
|
||||
let it run over night - your computer might become unresponsive from
|
||||
time to time, due to the heavy CPU and memory load, which tends to
|
||||
occur, when converting 54000x27000 images. ;-)
|
||||
I also recommend to deactivate swapping!
|
||||
$ sudo swapoff -a
|
||||
To reactivate swapping do:
|
||||
$ sudo swapon -a
|
||||
|
||||
This script relies on wget and imagemagick. Both are easily installed
|
||||
by your systems package-management-system.
|
||||
(On Debian/Ubuntu this is "apt-get")
|
||||
|
||||
So, on Debian for instance, you only need to put the following into
|
||||
the console:
|
||||
|
||||
$ sudo apt-get install wget imagemagick
|
||||
|
||||
Depending on your distro, the package names might differ slightly! Use
|
||||
a search engine of your choice to find out, how the packages are named
|
||||
in your distro!
|
||||
|
||||
You may want to check:
|
||||
|
||||
$ apt search imagemagick
|
||||
|
||||
|
||||
------------------------------------
|
||||
Targets:
|
||||
|
||||
world
|
||||
Generates the world tiles, needed to run FG with EarthView.
|
||||
You will find the results in output/[$resolution]/*. Copy
|
||||
these into $FGDATA/Models/Astro/*. More about the installation
|
||||
of these textures can be found here:
|
||||
http://wiki.flightgear.org/Earthview#Customization
|
||||
|
||||
clouds
|
||||
Generates the cloud tiles, needed to run FG with EarthView.
|
||||
The locations are the same as the other textures mentioned
|
||||
above. Note that clouds are only available with up to 8k
|
||||
resolution, due to the available data at NASA.
|
||||
|
||||
all
|
||||
Converts everything needed for a full-blown earthview texture
|
||||
set. Does the same as:
|
||||
$ ./convert.sh world clouds
|
||||
|
||||
|
||||
Options:
|
||||
|
||||
1k | 2k | 4k | 8k | 16k
|
||||
Lets you specify a desired resolution of the textures.
|
||||
Possible values are 1k, 2k, 4k, 8k and 16k. If nothing is
|
||||
specified, the script will generate all of the resolutions.
|
||||
16k is only available for earth textures.
|
||||
|
||||
nasa
|
||||
Causes the script to download directly from
|
||||
http://visibleearth.nasa.gov . If omitted the script will
|
||||
download from
|
||||
https://musicchris.de/download/FG/EarthView/raw-data-NASA.7z
|
||||
which is much faster!
|
||||
Uses wget either way.
|
||||
|
||||
no-download
|
||||
Causes the script to skip the download function. If you
|
||||
already have the source images, then you don't need to
|
||||
re-download them. (About 2.4GB!)
|
||||
If omitted, the script will download the source images from
|
||||
https://musicchris.de/download/FG/EarthView/raw-data-NASA.7z
|
||||
|
||||
cleanup
|
||||
Deletes the temporary files created during texture generation.
|
||||
These can be found in tmp/
|
||||
Note: if for some reason you later want some other resolution,
|
||||
then it's good to have the data there. So only do this, when
|
||||
you're quite sure that you're done.
|
||||
Frees up a lot of disk-space! Which would have to be
|
||||
regenerated if needed again.
|
||||
|
||||
rebuild
|
||||
Deletes only the temporary files of the given target. So if
|
||||
you call './convert.sh rebuild world' the script will delete
|
||||
all corresponding temp-files of the target world, which will
|
||||
trigger a complete regeneration of the relevant (instead of
|
||||
skipping existing files)
|
||||
|
||||
check
|
||||
Creates mosaics of the tiles, so you can look at them and see
|
||||
if all went well.
|
||||
1403
Nasa2FGearthview/convert.sh
Executable file
1403
Nasa2FGearthview/convert.sh
Executable file
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,10 @@ fi
|
||||
|
||||
VERSION=`cat flightgear/version`
|
||||
|
||||
#####################################################################################
|
||||
# ensure fgrcc can run when linked against libSimGearCore, for example
|
||||
export LD_LIBRARY_PATH=$WORKSPACE/dist/lib64:$WORKSPACE/dist/lib:$LD_LIBRARY_PATH
|
||||
|
||||
#####################################################################################
|
||||
# remove old and create fresh build directories
|
||||
cd $WORKSPACE
|
||||
@@ -14,7 +18,6 @@ mkdir -p sgBuild
|
||||
mkdir -p fgBuild
|
||||
mkdir -p output
|
||||
rm -rf output/*
|
||||
rm -rf dist/*
|
||||
|
||||
#####################################################################################
|
||||
echo "Starting on SimGear"
|
||||
@@ -38,7 +41,7 @@ cp simgear-*.tar.bz2 ../output/.
|
||||
#####################################################################################
|
||||
echo "Starting on FlightGear"
|
||||
cd ../fgBuild
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DSIMGEAR_SHARED:BOOL="ON" ../flightgear
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DSIMGEAR_SHARED:BOOL="ON" -DFG_BUILD_TYPE=Release ../flightgear
|
||||
|
||||
# compile
|
||||
make
|
||||
@@ -60,4 +63,3 @@ echo "Assembling base package"
|
||||
cd $WORKSPACE
|
||||
|
||||
tar cjf output/FlightGear-$VERSION-data.tar.bz2 fgdata/
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
|
||||
IF NOT DEFINED WORKSPACE SET WORKSPACE=%~dp0
|
||||
IF NOT DEFINED IS_NIGHTLY_BUILD SET IS_NIGHTLY_BUILD=1
|
||||
|
||||
IF %IS_NIGHTLY_BUILD% EQU 1 (
|
||||
SET FGBUILDTYPE=Nightly
|
||||
) ELSE (
|
||||
SET FGBUILDTYPE=Release
|
||||
)
|
||||
|
||||
REM following are for testing the script locally
|
||||
REM SET PATH=%PATH%;%ProgramFiles%\CMake\bin;%ProgramFiles(x86)%\"Inno Setup 5"\
|
||||
@@ -13,14 +20,14 @@ SET OSG64=%WORKSPACE%\install\msvc140-64\OpenSceneGraph
|
||||
REM 32bits
|
||||
md build-sg32
|
||||
md build-fg32
|
||||
md build-fgrun32
|
||||
cd build-sg32
|
||||
cmake ..\simgear -G "Visual Studio 14" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DOSG_FSTREAM_EXPORT_FIXED=1 ^
|
||||
-DCMAKE_PREFIX_PATH:PATH=%OSG32% ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140
|
||||
cmake --build . --config Release --target INSTALL
|
||||
cmake --build . --config RelWithDebInfo --target INSTALL
|
||||
|
||||
cd ..\build-fg32
|
||||
cmake ..\flightgear -G "Visual Studio 14" ^
|
||||
@@ -28,53 +35,42 @@ cmake ..\flightgear -G "Visual Studio 14" ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140 ^
|
||||
-DCMAKE_PREFIX_PATH:PATH=%WORKSPACE%/install/msvc140/OpenSceneGraph ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DCMAKE_PREFIX_PATH=%QT5SDK32%;%OSG32%
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fgrun32
|
||||
cmake ..\fgrun -G "Visual Studio 14" ^
|
||||
-DMSVC_3RDPARTY_ROOT:PATH=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DCMAKE_PREFIX_PATH:PATH=%OSG32% ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140
|
||||
cmake --build . --config Release --target INSTALL
|
||||
-DOSG_FSTREAM_EXPORT_FIXED=1 ^
|
||||
-DCMAKE_PREFIX_PATH=%QT5SDK32%;%OSG32% ^
|
||||
-DFG_BUILD_TYPE=%FGBUILDTYPE%
|
||||
cmake --build . --config RelWithDebInfo --target INSTALL
|
||||
|
||||
cd ..
|
||||
|
||||
REM 64 bits
|
||||
md build-sg64
|
||||
md build-fg64
|
||||
md build-fgrun64
|
||||
|
||||
cd build-sg64
|
||||
cmake ..\SimGear -G "Visual Studio 14 Win64" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DOSG_FSTREAM_EXPORT_FIXED=1 ^
|
||||
-DCMAKE_PREFIX_PATH:PATH=%OSG64% ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140-64
|
||||
cmake --build . --config Release --target INSTALL
|
||||
cmake --build . --config RelWithDebInfo --target INSTALL
|
||||
|
||||
cd ..\build-fg64
|
||||
cmake ..\flightgear -G "Visual Studio 14 Win64" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140-64 ^
|
||||
-DCMAKE_PREFIX_PATH=%QT5SDK64%;%OSG64%
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fgrun64
|
||||
cmake ..\fgrun -G "Visual Studio 14 Win64" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-DBOOST_ROOT=%WORKSPACE%/windows-3rd-party ^
|
||||
-DCMAKE_PREFIX_PATH:PATH=%OSG64% ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc140-64
|
||||
|
||||
cmake --build . --config Release --target INSTALL
|
||||
-DCMAKE_PREFIX_PATH=%QT5SDK64%;%OSG64% ^
|
||||
-DOSG_FSTREAM_EXPORT_FIXED=1 ^
|
||||
-DFG_BUILD_TYPE=%FGBUILDTYPE%
|
||||
cmake --build . --config RelWithDebInfo --target INSTALL
|
||||
|
||||
cd ..
|
||||
|
||||
REM Qt5 deployment
|
||||
%QT5SDK32%\bin\windeployqt --release --list target %WORKSPACE%/install/msvc140/bin/fgfs.exe
|
||||
%QT5SDK64%\bin\windeployqt --release --list target %WORKSPACE%/install/msvc140-64/bin/fgfs.exe
|
||||
SET QMLDIR=%WORKSPACE%/flightgear/src/GUI/qml
|
||||
%QT5SDK32%\bin\windeployqt --release --list target --qmldir %QMLDIR% %WORKSPACE%/install/msvc140/bin/fgfs.exe
|
||||
%QT5SDK64%\bin\windeployqt --release --list target --qmldir %QMLDIR% %WORKSPACE%/install/msvc140-64/bin/fgfs.exe
|
||||
|
||||
REM build setup
|
||||
ECHO Packaging root is %WORKSPACE%
|
||||
@@ -85,9 +81,10 @@ subst X: %WORKSPACE%.
|
||||
REM ensure output dir is clean since we upload the entirety of it
|
||||
rmdir /S /Q output
|
||||
|
||||
REM archiving PDB files
|
||||
copy %WORKSPACE%\build-fg32\src\Main\RelWithDebInfo\fgfs.pdb %WORKSPACE%\Output\fgfs-x86-%BUILD_NUMBER%.pdb
|
||||
copy %WORKSPACE%\build-fg64\src\Main\RelWithDebInfo\fgfs.pdb %WORKSPACE%\Output\fgfs-x64-%BUILD_NUMBER%.pdb
|
||||
SET CRASHFIX_UPLOAD_URL=http://crashes.flightgear.org/index.php/debugInfo/uploadExternal
|
||||
SET FGFS_PDB=src\Main\RelWithDebInfo\fgfs.pdb
|
||||
ECHO Uploading PDB files to %CRASHFIX_UPLOAD_URL%
|
||||
upload -v -u %CRASHFIX_UPLOAD_URL% FlightGear %WORKSPACE%\build-fg32\%FGFS_PDB% %WORKSPACE%\build-fg64\%FGFS_PDB%
|
||||
|
||||
REM indirect way to get command output into an environment variable
|
||||
set PATH=%OSG32%\bin;%PATH%
|
||||
@@ -104,17 +101,17 @@ IF %IS_NIGHTLY_BUILD% EQU 1 (
|
||||
REM FlightGear nightly: with fgdata, output filename would be "FlightGear-x.x.x-nightly-full.exe"
|
||||
CALL :writeBaseConfig
|
||||
CALL :writeNightlyFullConfig
|
||||
iscc FlightGear.iss
|
||||
iscc /Q FlightGear.iss
|
||||
|
||||
REM FlightGear nightly: without fgdata, output filename would be "FlightGear-x.x.x-nightly.exe"
|
||||
CALL :writeBaseConfig
|
||||
CALL :writeNightlyDietConfig
|
||||
iscc FlightGear.iss
|
||||
iscc /Q FlightGear.iss
|
||||
) ELSE (
|
||||
REM FlightGear release: with fgdata, output filename would be "FlightGear-x.x.x.exe"
|
||||
CALL :writeBaseConfig
|
||||
CALL :writeReleaseConfig
|
||||
iscc FlightGear.iss
|
||||
iscc /Q FlightGear.iss
|
||||
)
|
||||
GOTO End
|
||||
|
||||
|
||||
306
catalog/catalog.py
Normal file
306
catalog/catalog.py
Normal file
@@ -0,0 +1,306 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import lxml.etree as ET
|
||||
import os
|
||||
import re
|
||||
import sgprops
|
||||
import sys
|
||||
import catalogTags
|
||||
|
||||
CATALOG_VERSION = 4
|
||||
quiet = False
|
||||
verbose = False
|
||||
|
||||
def warning(msg):
|
||||
if not quiet:
|
||||
print(msg)
|
||||
|
||||
def log(msg):
|
||||
if verbose:
|
||||
print(msg)
|
||||
|
||||
# xml node (robust) get text helper
|
||||
def get_xml_text(e):
|
||||
if e != None and e.text != None:
|
||||
return e.text
|
||||
else:
|
||||
return ''
|
||||
|
||||
# return all available aircraft information from the set file as a
|
||||
# dict
|
||||
def scan_set_file(aircraft_dir, set_file, includes):
|
||||
base_file = os.path.basename(set_file)
|
||||
base_id = base_file[:-8]
|
||||
set_path = os.path.join(aircraft_dir, set_file)
|
||||
|
||||
includes.append(aircraft_dir)
|
||||
root_node = sgprops.readProps(set_path, includePaths = includes)
|
||||
|
||||
if not root_node.hasChild("sim"):
|
||||
return None
|
||||
|
||||
sim_node = root_node.getChild("sim")
|
||||
if sim_node == None:
|
||||
return None
|
||||
|
||||
# allow -set.xml files to specifcially exclude themselves from
|
||||
# the creation process, by setting <exclude-from-catalog>true</>
|
||||
if (sim_node.getValue("exclude-from-catalog", False) == True):
|
||||
return None
|
||||
|
||||
variant = {}
|
||||
name = sim_node.getValue("description", None)
|
||||
if (name == None or len(name) == 0):
|
||||
warning("Set file " + set_file + " is missing a <description>, skipping")
|
||||
return None
|
||||
|
||||
variant['name'] = name
|
||||
variant['status'] = sim_node.getValue("status", None)
|
||||
|
||||
if sim_node.hasChild('authors'):
|
||||
# aircraft has structured authors data, handle that
|
||||
variant['authors'] = extract_authors(sim_node.getChild('authors'))
|
||||
|
||||
elif sim_node.hasChild('author'):
|
||||
variant['author'] = sim_node.getValue("author", None)
|
||||
|
||||
if sim_node.hasChild('long-description'):
|
||||
variant['description'] = sim_node.getValue("long-description", None)
|
||||
variant['id'] = base_id
|
||||
|
||||
# allow -set.xml files to declare themselves as primary.
|
||||
# we use this avoid needing a variant-of in every other -set.xml
|
||||
variant['primary-set'] = sim_node.getValue('primary-set', False)
|
||||
|
||||
# extract and record previews for each variant
|
||||
if sim_node.hasChild('previews'):
|
||||
variant['previews'] = extract_previews(sim_node.getChild('previews'), aircraft_dir)
|
||||
|
||||
if sim_node.hasChild('rating'):
|
||||
rating_node = sim_node.getChild("rating")
|
||||
variant['rating_FDM'] = rating_node.getValue("FDM", 0)
|
||||
variant['rating_systems'] = rating_node.getValue("systems", 0)
|
||||
variant['rating_cockpit'] = rating_node.getValue("cockpit", 0)
|
||||
variant['rating_model'] = rating_node.getValue("model", 0)
|
||||
|
||||
if sim_node.hasChild('tags'):
|
||||
variant['tags'] = extract_tags(sim_node.getChild('tags'), set_file)
|
||||
|
||||
if sim_node.hasChild('thumbnail'):
|
||||
variant['thumbnail'] = sim_node.getValue("thumbnail", None)
|
||||
|
||||
variant['variant-of'] = sim_node.getValue("variant-of", None)
|
||||
|
||||
if sim_node.hasChild('minimum-fg-version'):
|
||||
variant['minimum-fg-version'] = sim_node.getValue('minimum-fg-version', None)
|
||||
|
||||
#print ' ', variant
|
||||
return variant
|
||||
|
||||
def extract_previews(previews_node, aircraft_dir):
|
||||
result = []
|
||||
for node in previews_node.getChildren("preview"):
|
||||
previewType = node.getValue("type", None)
|
||||
previewPath = node.getValue("path", None)
|
||||
|
||||
# check path exists in base-name-dir
|
||||
fullPath = os.path.join(aircraft_dir, previewPath)
|
||||
if not os.path.isfile(fullPath):
|
||||
warning("Bad preview path, skipping:" + fullPath)
|
||||
continue
|
||||
result.append({'type':previewType, 'path':previewPath})
|
||||
|
||||
return result
|
||||
|
||||
def extract_tags(tags_node, set_path):
|
||||
result = []
|
||||
for node in tags_node.getChildren("tag"):
|
||||
tag = node.value
|
||||
# check tag is in the allowed list
|
||||
if not catalogTags.isValidTag(tag):
|
||||
warning("Unknown tag value:" + tag + " in " + set_path)
|
||||
result.append(tag)
|
||||
|
||||
return result
|
||||
|
||||
def extract_authors(authors_node):
|
||||
result = []
|
||||
for author in authors_node.getChildren("author"):
|
||||
authorName = author.getValue("name", None)
|
||||
if (authorName == None):
|
||||
continue
|
||||
|
||||
authorNick = author.getValue("nick", None)
|
||||
authorEmail = author.getValue("email", None)
|
||||
authorDesc = author.getValue("description", None)
|
||||
|
||||
result.append({'name':authorName, 'nick':authorNick, 'email':authorEmail, 'description':authorDesc})
|
||||
return result
|
||||
|
||||
# scan all the -set.xml files in an aircraft directory. Returns a
|
||||
# package dict and a list of variants.
|
||||
def scan_aircraft_dir(aircraft_dir, includes):
|
||||
setDicts = []
|
||||
primaryAircraft = []
|
||||
package = None
|
||||
|
||||
files = os.listdir(aircraft_dir)
|
||||
for file in sorted(files, key=lambda s: s.lower()):
|
||||
if file.endswith('-set.xml'):
|
||||
# print 'trying:', file
|
||||
try:
|
||||
d = scan_set_file(aircraft_dir, file, includes)
|
||||
if d == None:
|
||||
continue
|
||||
except:
|
||||
print "Skipping set file since couldn't be parsed:", os.path.join(aircraft_dir, file), sys.exc_info()[0]
|
||||
continue
|
||||
|
||||
setDicts.append(d)
|
||||
if d['primary-set']:
|
||||
# ensure explicit primary-set aircraft goes first
|
||||
primaryAircraft.insert(0, d)
|
||||
elif d['variant-of'] == None:
|
||||
primaryAircraft.append(d)
|
||||
|
||||
# print setDicts
|
||||
if len(setDicts) == 0:
|
||||
return None, None
|
||||
|
||||
# use the first one
|
||||
if len(primaryAircraft) == 0:
|
||||
print "Aircraft has no primary aircraft at all:", aircraft_dir
|
||||
primaryAircraft = [setDicts[0]]
|
||||
|
||||
package = primaryAircraft[0]
|
||||
if not 'thumbnail' in package:
|
||||
if (os.path.exists(os.path.join(aircraft_dir, "thumbnail.jpg"))):
|
||||
package['thumbnail'] = "thumbnail.jpg"
|
||||
|
||||
# variants is just all the set dicts except the first one
|
||||
variants = setDicts
|
||||
variants.remove(package)
|
||||
return (package, variants)
|
||||
|
||||
# create an xml node with text content
|
||||
def make_xml_leaf(name, text):
|
||||
leaf = ET.Element(name)
|
||||
if text != None:
|
||||
if isinstance(text, (int, long)):
|
||||
leaf.text = str(text)
|
||||
else:
|
||||
leaf.text = text
|
||||
else:
|
||||
leaf.text = ''
|
||||
return leaf
|
||||
|
||||
def append_preview_nodes(node, variant, download_base, package_name):
|
||||
if not 'previews' in variant:
|
||||
return
|
||||
|
||||
for preview in variant['previews']:
|
||||
preview_node = ET.Element('preview')
|
||||
preview_url = download_base + 'previews/' + package_name + '_' + preview['path']
|
||||
preview_node.append( make_xml_leaf('type', preview['type']) )
|
||||
preview_node.append( make_xml_leaf('url', preview_url) )
|
||||
preview_node.append( make_xml_leaf('path', preview['path']) )
|
||||
node.append(preview_node)
|
||||
|
||||
def append_tag_nodes(node, variant):
|
||||
if not 'tags' in variant:
|
||||
return
|
||||
|
||||
for tag in variant['tags']:
|
||||
node.append(make_xml_leaf('tag', tag))
|
||||
|
||||
def append_author_nodes(node, info):
|
||||
if 'authors' in info:
|
||||
authors_node = ET.Element('authors')
|
||||
for a in info['authors']:
|
||||
a_node = ET.Element('author')
|
||||
a_node.append(make_xml_leaf('name', a['name']))
|
||||
if (a['email'] != None):
|
||||
a_node.append(make_xml_leaf('email', a['email']))
|
||||
if (a['nick'] != None):
|
||||
a_node.append(make_xml_leaf('nick', a['nick']))
|
||||
if (a['description'] != None):
|
||||
a_node.append(make_xml_leaf('description', a['description']))
|
||||
authors_node.append(a_node)
|
||||
|
||||
node.append(authors_node)
|
||||
elif 'author' in info:
|
||||
# traditional single author string
|
||||
node.append( make_xml_leaf('author', info['author']) )
|
||||
|
||||
def make_aircraft_node(aircraftDirName, package, variants, downloadBase):
|
||||
#print "package:", package
|
||||
#print "variants:", variants
|
||||
package_node = ET.Element('package')
|
||||
package_node.append( make_xml_leaf('name', package['name']) )
|
||||
package_node.append( make_xml_leaf('status', package['status']) )
|
||||
|
||||
append_author_nodes(package_node, package)
|
||||
|
||||
if 'description' in package:
|
||||
package_node.append( make_xml_leaf('description', package['description']) )
|
||||
|
||||
if 'minimum-fg-version' in package:
|
||||
package_node.append( make_xml_leaf('minimum-fg-version', package['minimum-fg-version']) )
|
||||
|
||||
if 'rating_FDM' in package or 'rating_systems' in package \
|
||||
or 'rating_cockpit' in package or 'rating_model' in package:
|
||||
rating_node = ET.Element('rating')
|
||||
package_node.append(rating_node)
|
||||
rating_node.append( make_xml_leaf('FDM',
|
||||
package['rating_FDM']) )
|
||||
rating_node.append( make_xml_leaf('systems',
|
||||
package['rating_systems']) )
|
||||
rating_node.append( make_xml_leaf('cockpit',
|
||||
package['rating_cockpit']) )
|
||||
rating_node.append( make_xml_leaf('model',
|
||||
package['rating_model']) )
|
||||
package_node.append( make_xml_leaf('id', package['id']) )
|
||||
for variant in variants:
|
||||
variant_node = ET.Element('variant')
|
||||
package_node.append(variant_node)
|
||||
variant_node.append( make_xml_leaf('id', variant['id']) )
|
||||
variant_node.append( make_xml_leaf('name', variant['name']) )
|
||||
if 'description' in variant:
|
||||
variant_node.append( make_xml_leaf('description', variant['description']) )
|
||||
|
||||
if 'author' in variant:
|
||||
variant_node.append( make_xml_leaf('author', variant['author']) )
|
||||
|
||||
if 'thumbnail' in variant:
|
||||
# note here we prefix with the package name, since the thumbnail path
|
||||
# is assumed to be unique within the package
|
||||
thumbUrl = downloadBase + "thumbnails/" + aircraftDirName + '_' + variant['thumbnail']
|
||||
variant_node.append(make_xml_leaf('thumbnail', thumbUrl))
|
||||
variant_node.append(make_xml_leaf('thumbnail-path', variant['thumbnail']))
|
||||
|
||||
variantOf = variant['variant-of']
|
||||
if variantOf is None:
|
||||
variant_node.append(make_xml_leaf('variant-of', '_primary_'))
|
||||
else:
|
||||
variant_node.append(make_xml_leaf('variant-of', variantOf))
|
||||
|
||||
append_preview_nodes(variant_node, variant, downloadBase, aircraftDirName)
|
||||
append_tag_nodes(variant_node, variant)
|
||||
append_author_nodes(variant_node, variant)
|
||||
|
||||
package_node.append( make_xml_leaf('dir', aircraftDirName) )
|
||||
|
||||
download_url = downloadBase + aircraftDirName + '.zip'
|
||||
package_node.append( make_xml_leaf('url', download_url) )
|
||||
|
||||
if 'thumbnail' in package:
|
||||
thumbnail_url = downloadBase + 'thumbnails/' + aircraftDirName + '_' + package['thumbnail']
|
||||
package_node.append( make_xml_leaf('thumbnail', thumbnail_url) )
|
||||
package_node.append( make_xml_leaf('thumbnail-path', package['thumbnail']))
|
||||
|
||||
append_preview_nodes(package_node, package, downloadBase, aircraftDirName)
|
||||
append_tag_nodes(package_node, package)
|
||||
|
||||
return package_node
|
||||
164
catalog/catalogTags.py
Normal file
164
catalog/catalogTags.py
Normal file
@@ -0,0 +1,164 @@
|
||||
aircraftTypeTags = [
|
||||
"aerobatic",
|
||||
"airship",
|
||||
"balloon",
|
||||
"bizjet",
|
||||
"bomber",
|
||||
"cargo",
|
||||
"carrier",
|
||||
"fighter",
|
||||
"ga",
|
||||
"glider",
|
||||
"groundvehicle",
|
||||
"helicopter",
|
||||
"racer",
|
||||
"spaceship",
|
||||
"tanker",
|
||||
"trainer",
|
||||
"transport",
|
||||
"ultralight",
|
||||
"reconnaissance",
|
||||
"seacraft",
|
||||
"crop-duster",
|
||||
"bush-plane"
|
||||
]
|
||||
|
||||
manufacturerTags = [
|
||||
"airbus",
|
||||
"antonov",
|
||||
"atr",
|
||||
"avro",
|
||||
"bell",
|
||||
"bleriot",
|
||||
"boeing",
|
||||
"bombardier",
|
||||
"caudron",
|
||||
"cessna",
|
||||
"consolidated",
|
||||
"dassault",
|
||||
"diamond",
|
||||
"dornier",
|
||||
"douglas",
|
||||
"embraer",
|
||||
"eurocopter",
|
||||
"fairchild",
|
||||
"fairey",
|
||||
"focke-wulf",
|
||||
"fokker",
|
||||
"general-dynamics",
|
||||
"gotha",
|
||||
"grumman",
|
||||
"handley-page",
|
||||
"hawker",
|
||||
"heinkel",
|
||||
"ilyushin",
|
||||
"junkers",
|
||||
"lockheed",
|
||||
"mc-donnell-douglas",
|
||||
"messerschmitt",
|
||||
"mikoyan-gurevich",
|
||||
"mitsubishi",
|
||||
"north-american",
|
||||
"northrop",
|
||||
"pilatus",
|
||||
"piper",
|
||||
"republic",
|
||||
"robin",
|
||||
"saab",
|
||||
"short",
|
||||
"sopwith",
|
||||
"spad",
|
||||
"sukhoi",
|
||||
"supermarine",
|
||||
"tupolev",
|
||||
"vickers",
|
||||
"vought",
|
||||
"yakovlev"
|
||||
]
|
||||
|
||||
eraTags = [
|
||||
"1910s",
|
||||
"1920s",
|
||||
"1930s",
|
||||
"1940s",
|
||||
"1950s",
|
||||
"1960s",
|
||||
"1970s",
|
||||
"1980s",
|
||||
"1990s",
|
||||
"2000s",
|
||||
"2010s",
|
||||
"coldwar",
|
||||
"early-pioneers",
|
||||
"golden-age",
|
||||
"gulfwar1",
|
||||
"gulfwar2",
|
||||
"vietnam",
|
||||
"ww1",
|
||||
"ww2"
|
||||
]
|
||||
|
||||
featureTags = [
|
||||
"aerobatic",
|
||||
"airship",
|
||||
"amphibious",
|
||||
"biplane",
|
||||
"canard",
|
||||
"castering-wheel",
|
||||
"delta",
|
||||
"etops",
|
||||
"experimental",
|
||||
"fictional",
|
||||
"fixed-gear",
|
||||
"floats",
|
||||
"glass-cockpit",
|
||||
"high-wing",
|
||||
"h-tail",
|
||||
"hud",
|
||||
"ifr",
|
||||
"prototype",
|
||||
"refuel",
|
||||
"retractable-gear",
|
||||
"seaplane",
|
||||
"skis",
|
||||
"stol",
|
||||
"supersonic",
|
||||
"t-tail",
|
||||
"tail-dragger",
|
||||
"tricycle",
|
||||
"tail-hook",
|
||||
"triplane",
|
||||
"v-tail",
|
||||
"variable-geometry",
|
||||
"vtol",
|
||||
"wing-fold"
|
||||
]
|
||||
|
||||
propulsionTags = [
|
||||
"afterburner",
|
||||
"diesel",
|
||||
"electric",
|
||||
"jet",
|
||||
"propeller",
|
||||
"piston",
|
||||
"radial",
|
||||
"rocket",
|
||||
"single-engine",
|
||||
"supercharged",
|
||||
"turboprop",
|
||||
"twin-engine",
|
||||
"variable-pitch",
|
||||
"fixed-pitch"
|
||||
]
|
||||
|
||||
simFeatureTags = [
|
||||
"dual-controls",
|
||||
"rembrandt",
|
||||
"tow",
|
||||
"wildfire"
|
||||
]
|
||||
|
||||
tags = aircraftTypeTags + manufacturerTags + eraTags + simFeatureTags + propulsionTags + featureTags
|
||||
|
||||
def isValidTag(maybeTag):
|
||||
return maybeTag in tags
|
||||
@@ -11,6 +11,9 @@
|
||||
<skip>c172</skip>
|
||||
<skip>tu134</skip>
|
||||
</scm>
|
||||
<include-dir>/home/curt/Projects/FlightGear/flightgear-fgdata</include-dir>
|
||||
<include-dir>/home/curt/Projects/FlightGear/flightgear-fgaddon</include-dir>
|
||||
|
||||
<!-- <scm>
|
||||
<type>git</type>
|
||||
<update type="bool">false</update>
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
<version n="1">3.5.*</version>
|
||||
<version n="2">3.6.*</version>
|
||||
<version n="3">3.7.*</version>
|
||||
<version n="4">2016.1.*</version>
|
||||
<version n="4">2016.*.*</version>
|
||||
<version n="5">2016.*.*</version>
|
||||
<version n="6">2017.*.*</version>
|
||||
<version n="7">2018.*.*</version>
|
||||
<id>org.flightgear.fgaddon</id>
|
||||
<license>GPL</license>
|
||||
<url>http://mirrors.ibiblio.org/flightgear/ftp/Aircraft/catalog.xml</url>
|
||||
<name>FlightGear Aircraft Distribution From fgaddon</name>
|
||||
<name>FlightGear aircraft distribution from fgaddon</name>
|
||||
<description>This hangar provides aircraft officially supported and maintained by the FlightGear project, under a free-software license.</description>
|
||||
<de>
|
||||
<description>Auf Deutsch</description>
|
||||
|
||||
@@ -133,6 +133,8 @@ class Node(object):
|
||||
n.set('type', "bool")
|
||||
except UnicodeEncodeError:
|
||||
print "Encoding error with", self._value, type(self._value)
|
||||
except:
|
||||
print "Some other exceptiong in sgprops._createXMLElement()"
|
||||
|
||||
# index in parent
|
||||
if (self.index != 0):
|
||||
@@ -144,6 +146,22 @@ class Node(object):
|
||||
|
||||
return n;
|
||||
|
||||
class ParseState:
|
||||
def __init__(self):
|
||||
self._counters = {}
|
||||
|
||||
def getNextIndex(self, name):
|
||||
if name in self._counters:
|
||||
self._counters[name] += 1
|
||||
else:
|
||||
self._counters[name] = 0
|
||||
return self._counters[name]
|
||||
|
||||
def recordExplicitIndex(self, name, index):
|
||||
if not name in self._counters:
|
||||
self._counters[name] = index
|
||||
else:
|
||||
self._counters[name] = max(self._counters[name], index)
|
||||
|
||||
class PropsHandler(handler.ContentHandler):
|
||||
def __init__(self, root = None, path = None, includePaths = []):
|
||||
@@ -152,6 +170,7 @@ class PropsHandler(handler.ContentHandler):
|
||||
self._basePath = os.path.dirname(path)
|
||||
self._includes = includePaths
|
||||
self._locator = None
|
||||
self._stateStack = [ParseState()]
|
||||
|
||||
if root is None:
|
||||
# make a nameless root node
|
||||
@@ -164,20 +183,28 @@ class PropsHandler(handler.ContentHandler):
|
||||
def startElement(self, name, attrs):
|
||||
self._content = None
|
||||
if (name == 'PropertyList'):
|
||||
# still need to handle includes on the root element
|
||||
if 'include' in attrs.keys():
|
||||
self.handleInclude(attrs['include'])
|
||||
return
|
||||
|
||||
currentState = self._stateStack[-1]
|
||||
if 'n' in attrs.keys():
|
||||
try:
|
||||
index = int(attrs['n'])
|
||||
except:
|
||||
print "Invalid index at line:", self._locator.getLineNumber(), "of", self._path
|
||||
self._current = self._current.addChild(name)
|
||||
return
|
||||
raise IndexError("Invalid index at line:", self._locator.getLineNumber(), "of", self._path)
|
||||
|
||||
currentState.recordExplicitIndex(name, index)
|
||||
self._current = self._current.getChild(name, index, create=True)
|
||||
else:
|
||||
self._current = self._current.addChild(name)
|
||||
index = currentState.getNextIndex(name)
|
||||
# important we use getChild here, so that includes are resolved
|
||||
# correctly
|
||||
self._current = self._current.getChild(name, index, create=True)
|
||||
|
||||
self._stateStack.append(ParseState())
|
||||
|
||||
if 'include' in attrs.keys():
|
||||
self.handleInclude(attrs['include'])
|
||||
@@ -228,6 +255,7 @@ class PropsHandler(handler.ContentHandler):
|
||||
self._current = self._current.parent
|
||||
self._content = None
|
||||
self._currentTy = None
|
||||
self._stateStack.pop()
|
||||
|
||||
|
||||
def parsePropsBool(self, content):
|
||||
8
catalog/testData/Aircraft/c150/c150-set.xml
Normal file
8
catalog/testData/Aircraft/c150/c150-set.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<sim>
|
||||
<name>c150</name>
|
||||
<description>Cessna 150</description>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
9
catalog/testData/Aircraft/c172/c172-set.xml
Normal file
9
catalog/testData/Aircraft/c172/c172-set.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<sim>
|
||||
<name>c172</name>
|
||||
<description>Cessna 172P</description>
|
||||
<author>Wilbur Wright</author>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
0
catalog/testData/Aircraft/f16/Previews/cockpit.png
Normal file
0
catalog/testData/Aircraft/f16/Previews/cockpit.png
Normal file
24
catalog/testData/Aircraft/f16/f16-common.xml
Normal file
24
catalog/testData/Aircraft/f16/f16-common.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<sim include="settings-common.xml">
|
||||
<authors>
|
||||
<author n="0">
|
||||
<name>Wilbur Wright</name>
|
||||
<email>ww@wright.com</email>
|
||||
<nick>wilburw</nick>
|
||||
<description>Model, FDM and cockpit</description>
|
||||
</author>
|
||||
<author n="1">
|
||||
<name>Orville Wright</name>
|
||||
<description>Testing and systems</description>
|
||||
</author>
|
||||
</authors>
|
||||
<tags>
|
||||
<tag>fighter</tag>
|
||||
<tag>1980s</tag>
|
||||
<tag>glass-cockpit</tag>
|
||||
</tags>
|
||||
<minimum-fg-version>2017.4</minimum-fg-version>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
11
catalog/testData/Aircraft/f16/f16-excluded-set.xml
Normal file
11
catalog/testData/Aircraft/f16/f16-excluded-set.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<exclude-from-catalog type="bool">true</exclude-from-catalog>
|
||||
<name>f16-excluded</name>
|
||||
<description>Fine</description>
|
||||
<long-description>Blah blah blah</long-description>
|
||||
<variant-of>f16a</variant-of>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
11
catalog/testData/Aircraft/f16/f16-trainer-set.xml
Normal file
11
catalog/testData/Aircraft/f16/f16-trainer-set.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<name>f16-trainer</name>
|
||||
<description>F16 Trainer</description>
|
||||
<long-description>Twin-seat trainer version of the F16</long-description>
|
||||
|
||||
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
36
catalog/testData/Aircraft/f16/f16a-set.xml
Normal file
36
catalog/testData/Aircraft/f16/f16a-set.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<name>f16a</name>
|
||||
<description>F16-A</description>
|
||||
<long-description>The F16 is compact, light-weight multi-role fighter used around the world</long-description>
|
||||
|
||||
<primary-set type="bool">true</primary-set>
|
||||
|
||||
<rating>
|
||||
<FDM type="int">3</FDM>
|
||||
<systems type="int">1</systems>
|
||||
<cockpit type="int">2</cockpit>
|
||||
<model type="int">5</model>
|
||||
</rating>
|
||||
|
||||
<previews>
|
||||
<preview>
|
||||
<type>exterior</type>
|
||||
<splash type="bool">true</splash>
|
||||
<path>Previews/exterior-1.png</path>
|
||||
</preview>
|
||||
<preview>
|
||||
<type>exterior</type>
|
||||
<splash type="bool">true</splash>
|
||||
<path>Previews/exterior-f16a-2.png</path>
|
||||
</preview>
|
||||
<preview>
|
||||
<type>panel</type>
|
||||
<splash type="bool">false</splash>
|
||||
<path>Previews/cockpit.png</path>
|
||||
</preview>
|
||||
</previews>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
19
catalog/testData/Aircraft/f16/f16b-set.xml
Normal file
19
catalog/testData/Aircraft/f16/f16b-set.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<name>f16b</name>
|
||||
<description>F16-B</description>
|
||||
<long-description>The F16-B is an upgraded version of the F16A.</long-description>
|
||||
<variant-of>f16a</variant-of>
|
||||
|
||||
<authors n="0">
|
||||
<author n="0">
|
||||
<name>James T Kirk</name>
|
||||
<email>shatner@enterprise.com</email>
|
||||
<nick>starlover</nick>
|
||||
<description>Everything</description>
|
||||
</author>
|
||||
</authors>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
11
catalog/testData/Aircraft/f16/f16broken-set.xml
Normal file
11
catalog/testData/Aircraft/f16/f16broken-set.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<name>f16broken</name>
|
||||
<!-- <description></description> -->
|
||||
<description></description>
|
||||
<long-description>Blah blah blah</long-description>
|
||||
<variant-of>f16a</variant-of>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
10
catalog/testData/Aircraft/f16/f16c-set.xml
Normal file
10
catalog/testData/Aircraft/f16/f16c-set.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="f16-common.xml">
|
||||
<sim>
|
||||
<name>f16c</name>
|
||||
<description>F16-C</description>
|
||||
<long-description>The F16-C is an upgraded version of the F16A.</long-description>
|
||||
<variant-of>f16a</variant-of>
|
||||
</sim>
|
||||
|
||||
</PropertyList>
|
||||
0
catalog/testData/Aircraft/f16/thumbnail.jpg
Normal file
0
catalog/testData/Aircraft/f16/thumbnail.jpg
Normal file
12
catalog/testData/OtherDir/settings-common.xml
Normal file
12
catalog/testData/OtherDir/settings-common.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<!-- this file exists to test including + overlaying in the set XML -->
|
||||
|
||||
<PropertyList>
|
||||
<views>
|
||||
<view n="0">
|
||||
<foo>dsdddd</foo>
|
||||
</view>
|
||||
</views>
|
||||
|
||||
</PropertyList>
|
||||
11
catalog/testData/bad-index.xml
Normal file
11
catalog/testData/bad-index.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PropertyList>
|
||||
<sim>
|
||||
<!-- found in the F-15 XML -->
|
||||
<uhf n="[0]">
|
||||
<frequencies>
|
||||
<selected-mhz type="int">225000</selected-mhz>
|
||||
</frequencies>
|
||||
</uhf>
|
||||
</sim>
|
||||
</PropertyList>
|
||||
25
catalog/testData/props1.xml
Normal file
25
catalog/testData/props1.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<value type="int">42</value>
|
||||
|
||||
<thing>
|
||||
<value>apple</value>
|
||||
</thing>
|
||||
|
||||
<thing>
|
||||
<value>lemon</value>
|
||||
</thing>
|
||||
|
||||
<thing>
|
||||
<value>pear</value>
|
||||
</thing>
|
||||
|
||||
<!-- ensure explicit indexing works -->
|
||||
<sub>
|
||||
<value n="1">a</value>
|
||||
<value n="3">b</value>
|
||||
<value n="99">c</value>
|
||||
<value>d</value> <!-- should be assigned n=100 -->
|
||||
</sub>
|
||||
|
||||
</PropertyList>
|
||||
20
catalog/testData/props2.xml
Normal file
20
catalog/testData/props2.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList include="root-include.xml">
|
||||
<value type="int">33</value>
|
||||
|
||||
<thing>
|
||||
<value>apple</value>
|
||||
</thing>
|
||||
|
||||
<thing>
|
||||
<value>lemon</value>
|
||||
</thing>
|
||||
|
||||
|
||||
<sub include ="sub-include.xml">
|
||||
<!-- different index to avoid being included over -->
|
||||
<widget n="100" type="int">99</widget>
|
||||
|
||||
</sub>
|
||||
|
||||
</PropertyList>
|
||||
22
catalog/testData/root-include.xml
Normal file
22
catalog/testData/root-include.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<value type="int">42</value>
|
||||
<value type="int">43</value>
|
||||
<value type="int">44</value>
|
||||
|
||||
<sim>
|
||||
<views>
|
||||
</views>
|
||||
|
||||
<preview>
|
||||
</preview>
|
||||
|
||||
<preview>
|
||||
</preview>
|
||||
</sim>
|
||||
|
||||
<payload>
|
||||
<weight>
|
||||
</weight>
|
||||
</payload>
|
||||
</PropertyList>
|
||||
6
catalog/testData/sub-include.xml
Normal file
6
catalog/testData/sub-include.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<widget type="int">42</widget>
|
||||
<widget type="int">43</widget>
|
||||
<widget type="int">44</widget>
|
||||
</PropertyList>
|
||||
197
catalog/test_catalog.py
Executable file
197
catalog/test_catalog.py
Executable file
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import unittest
|
||||
import sgprops
|
||||
import os
|
||||
import catalog
|
||||
import lxml.etree as ET
|
||||
|
||||
catalog.quiet = True
|
||||
|
||||
class UpdateCatalogTests(unittest.TestCase):
|
||||
def test_scan_set(self):
|
||||
info = catalog.scan_set_file("testData/Aircraft/f16", "f16a-set.xml", ["testData/OtherDir"])
|
||||
self.assertEqual(info['id'], 'f16a')
|
||||
self.assertEqual(info['name'], 'F16-A')
|
||||
self.assertEqual(info['primary-set'], True)
|
||||
self.assertEqual(info['variant-of'], None)
|
||||
self.assertEqual(info['rating_FDM'], 3)
|
||||
self.assertEqual(info['rating_model'], 5)
|
||||
self.assertEqual(len(info['tags']), 3)
|
||||
self.assertEqual(info['minimum-fg-version'], '2017.4')
|
||||
|
||||
authorsArray = info['authors']
|
||||
self.assertNotIn('author', info)
|
||||
self.assertEqual(len(authorsArray), 2)
|
||||
|
||||
author0 = authorsArray[0]
|
||||
self.assertEqual(author0['name'], 'Wilbur Wright')
|
||||
self.assertEqual(author0['nick'], 'wilburw')
|
||||
self.assertEqual(author0['email'], 'ww@wright.com')
|
||||
|
||||
author1 = authorsArray[1]
|
||||
self.assertEqual(author1['name'], 'Orville Wright')
|
||||
# self.assertNotIn('nick', author1)
|
||||
# self.assertNotIn('email', author1)
|
||||
|
||||
def test_scan_dir(self):
|
||||
(pkg, variants) = catalog.scan_aircraft_dir("testData/Aircraft/f16", ["testData/OtherDir"])
|
||||
|
||||
self.assertEqual(pkg['id'], 'f16a')
|
||||
f16trainer = next(v for v in variants if v['id'] == 'f16-trainer')
|
||||
self.assertEqual(len(variants), 3)
|
||||
self.assertEqual(pkg['minimum-fg-version'], '2017.4')
|
||||
|
||||
# test variant relatonship between
|
||||
self.assertEqual(pkg['variant-of'], None)
|
||||
self.assertEqual(pkg['primary-set'], True)
|
||||
|
||||
self.assertEqual(f16trainer['variant-of'], None)
|
||||
self.assertEqual(f16trainer['primary-set'], False)
|
||||
|
||||
f16b = next(v for v in variants if v['id'] == 'f16b')
|
||||
self.assertEqual(f16b['variant-of'], 'f16a')
|
||||
self.assertEqual(f16b['primary-set'], False)
|
||||
|
||||
authorsArray = f16b['authors']
|
||||
self.assertNotIn('author', f16b)
|
||||
self.assertEqual(len(authorsArray), 2)
|
||||
|
||||
author0 = authorsArray[0]
|
||||
self.assertEqual(author0['name'], 'James T Kirk')
|
||||
self.assertEqual(author0['nick'], 'starlover')
|
||||
|
||||
f16c = next(v for v in variants if v['id'] == 'f16c')
|
||||
self.assertEqual(f16c['variant-of'], 'f16a')
|
||||
self.assertEqual(f16c['primary-set'], False)
|
||||
|
||||
authorsArray = f16c['authors']
|
||||
self.assertNotIn('author', f16c)
|
||||
self.assertEqual(len(authorsArray), 2)
|
||||
|
||||
# test some older constructs for compat
|
||||
def test_scan_dir_legacy(self):
|
||||
(pkg, variants) = catalog.scan_aircraft_dir("testData/Aircraft/c172", [])
|
||||
|
||||
self.assertEqual(pkg['id'], 'c172')
|
||||
self.assertEqual(pkg['author'], 'Wilbur Wright')
|
||||
|
||||
def test_extract_previews(self):
|
||||
info = catalog.scan_set_file("testData/Aircraft/f16", "f16a-set.xml", ["testData/OtherDir"])
|
||||
previews = info['previews']
|
||||
self.assertEqual(len(previews), 3)
|
||||
self.assertEqual(2, len([p for p in previews if p['type'] == 'exterior']))
|
||||
self.assertEqual(1, len([p for p in previews if p['type'] == 'panel']))
|
||||
self.assertEqual(1, len([p for p in previews if p['path'] == 'Previews/exterior-1.png']))
|
||||
|
||||
def test_extract_tags(self):
|
||||
info = catalog.scan_set_file("testData/Aircraft/f16", "f16a-set.xml", ["testData/OtherDir"])
|
||||
tags = info['tags']
|
||||
|
||||
def test_node_creation(self):
|
||||
(pkg, variants) = catalog.scan_aircraft_dir("testData/Aircraft/f16", ["testData/OtherDir"])
|
||||
|
||||
catalog_node = ET.Element('PropertyList')
|
||||
catalog_root = ET.ElementTree(catalog_node)
|
||||
|
||||
pkgNode = catalog.make_aircraft_node('f16', pkg, variants, "http://foo.com/testOutput/")
|
||||
catalog_node.append(pkgNode)
|
||||
|
||||
# write out so we can parse using sgprops
|
||||
# yes we are round-tripping via the disk, if you can improve
|
||||
# then feel free..
|
||||
if not os.path.isdir("testOutput"):
|
||||
os.mkdir("testOutput")
|
||||
|
||||
cat_file = os.path.join("testOutput", 'catalog_fragment.xml')
|
||||
catalog_root.write(cat_file, encoding='utf-8', xml_declaration=True, pretty_print=True)
|
||||
|
||||
parsed = sgprops.readProps(cat_file)
|
||||
parsedPkgNode = parsed.getChild("package")
|
||||
|
||||
self.assertEqual(parsedPkgNode.name, "package");
|
||||
|
||||
self.assertEqual(parsedPkgNode.getValue('id'), pkg['id']);
|
||||
self.assertEqual(parsedPkgNode.getValue('dir'), 'f16');
|
||||
self.assertEqual(parsedPkgNode.getValue('url'), 'http://foo.com/testOutput/f16.zip');
|
||||
self.assertEqual(parsedPkgNode.getValue('thumbnail'), 'http://foo.com/testOutput/thumbnails/f16_thumbnail.jpg');
|
||||
self.assertEqual(parsedPkgNode.getValue('thumbnail-path'), 'thumbnail.jpg');
|
||||
|
||||
self.assertEqual(parsedPkgNode.getValue('name'), pkg['name']);
|
||||
self.assertEqual(parsedPkgNode.getValue('description'), pkg['description']);
|
||||
|
||||
self.assertEqual(parsedPkgNode.getValue('minimum-fg-version'), "2017.4");
|
||||
|
||||
parsedVariants = parsedPkgNode.getChildren("variant")
|
||||
self.assertEqual(len(parsedVariants), 3)
|
||||
|
||||
# author data verification
|
||||
self.assertFalse(parsedPkgNode.hasChild('author'));
|
||||
parsedAuthors = parsedPkgNode.getChild("authors").getChildren('author')
|
||||
|
||||
self.assertEqual(len(parsedAuthors), 2)
|
||||
author1 = parsedAuthors[0]
|
||||
self.assertEqual(author1.getValue("name"), "Wilbur Wright")
|
||||
self.assertEqual(author1.getValue("nick"), "wilburw")
|
||||
self.assertEqual(author1.getValue("email"), "ww@wright.com")
|
||||
|
||||
author2 = parsedAuthors[1]
|
||||
self.assertEqual(author2.getValue("name"), "Orville Wright")
|
||||
|
||||
f16ANode = parsedPkgNode
|
||||
self.assertEqual(f16ANode.getValue('name'), 'F16-A');
|
||||
|
||||
for index, pv in enumerate(parsedVariants):
|
||||
var = variants[index]
|
||||
self.assertEqual(pv.getValue('name'), var['name']);
|
||||
self.assertEqual(pv.getValue('description'), var['description']);
|
||||
|
||||
if (var['id'] == 'f16-trainer'):
|
||||
self.assertEqual(pv.getValue('variant-of'), '_primary_')
|
||||
# self.assertEqual(pv.getValue('author'), "Wilbur Wright");
|
||||
elif (var['id'] == 'f16b'):
|
||||
self.assertEqual(pv.getValue('variant-of'), 'f16a')
|
||||
self.assertEqual(pv.getValue('description'), 'The F16-B is an upgraded version of the F16A.')
|
||||
|
||||
# variant author verification
|
||||
parsedAuthors = pv.getChild("authors").getChildren('author')
|
||||
author1 = parsedAuthors[0]
|
||||
self.assertEqual(author1.getValue("name"), "James T Kirk")
|
||||
self.assertEqual(author1.getValue("nick"), "starlover")
|
||||
self.assertEqual(author1.getValue("email"), "shatner@enterprise.com")
|
||||
self.assertEqual(author1.getValue("description"), "Everything")
|
||||
|
||||
def test_minimalAircraft(self):
|
||||
# test an aircraft with a deliberately spartan -set.xml file with
|
||||
# most interesting data missing
|
||||
(pkg, variants) = catalog.scan_aircraft_dir("testData/Aircraft/c150", ["testData/OtherDir"])
|
||||
|
||||
catalog_node = ET.Element('PropertyList')
|
||||
catalog_root = ET.ElementTree(catalog_node)
|
||||
|
||||
pkgNode = catalog.make_aircraft_node('c150', pkg, variants, "http://foo.com/testOutput/")
|
||||
catalog_node.append(pkgNode)
|
||||
|
||||
if not os.path.isdir("testOutput2"):
|
||||
os.mkdir("testOutput2")
|
||||
|
||||
cat_file = os.path.join("testOutput2", 'catalog_fragment.xml')
|
||||
catalog_root.write(cat_file, encoding='utf-8', xml_declaration=True, pretty_print=True)
|
||||
|
||||
parsed = sgprops.readProps(cat_file)
|
||||
parsedPkgNode = parsed.getChild("package")
|
||||
|
||||
self.assertEqual(parsedPkgNode.getValue('id'), pkg['id'])
|
||||
self.assertEqual(parsedPkgNode.getValue('dir'), 'c150')
|
||||
self.assertEqual(parsedPkgNode.getValue('url'), 'http://foo.com/testOutput/c150.zip')
|
||||
self.assertFalse(parsedPkgNode.hasChild('thumbnail'))
|
||||
self.assertFalse(parsedPkgNode.hasChild('thumbnail-path'));
|
||||
|
||||
self.assertEqual(parsedPkgNode.getValue('name'), pkg['name']);
|
||||
self.assertFalse(parsedPkgNode.hasChild('description'));
|
||||
self.assertFalse(parsedPkgNode.hasChild('author'));
|
||||
self.assertFalse(parsedPkgNode.hasChild('minimum-fg-version'));
|
||||
self.assertFalse(parsedPkgNode.hasChild('variant'));
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
61
catalog/test_sgprops.py
Executable file
61
catalog/test_sgprops.py
Executable file
@@ -0,0 +1,61 @@
|
||||
import unittest
|
||||
|
||||
import types
|
||||
import sgprops
|
||||
|
||||
class SGProps(unittest.TestCase):
|
||||
|
||||
def test_parse(self):
|
||||
parsed = sgprops.readProps("testData/props1.xml")
|
||||
|
||||
self.assertEqual(parsed.getValue("value"), 42)
|
||||
self.assertEqual(type(parsed.getValue("value")), types.IntType)
|
||||
|
||||
valNode = parsed.getChild("value")
|
||||
self.assertEqual(valNode.parent, parsed)
|
||||
self.assertEqual(valNode.name, "value")
|
||||
|
||||
self.assertEqual(valNode.value, 42)
|
||||
self.assertEqual(type(valNode.value), types.IntType)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
missingNode = parsed.getChild("missing")
|
||||
|
||||
things = parsed.getChildren("thing")
|
||||
self.assertEqual(len(things), 3)
|
||||
|
||||
self.assertEqual(things[0], parsed.getChild("thing", 0));
|
||||
self.assertEqual(things[1], parsed.getChild("thing", 1));
|
||||
self.assertEqual(things[2], parsed.getChild("thing", 2));
|
||||
|
||||
self.assertEqual(things[0].getValue("value"), "apple");
|
||||
self.assertEqual(things[1].getValue("value"), "lemon");
|
||||
self.assertEqual(things[2].getValue("value"), "pear");
|
||||
|
||||
def test_create(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_invalidIndex(self):
|
||||
with self.assertRaises(IndexError):
|
||||
parsed = sgprops.readProps("testData/bad-index.xml")
|
||||
|
||||
def test_include(self):
|
||||
parsed = sgprops.readProps("testData/props2.xml")
|
||||
|
||||
# test that value in main file over-rides the one in the include
|
||||
self.assertEqual(parsed.getValue("value"), 33)
|
||||
|
||||
# but these come from the included file
|
||||
self.assertEqual(parsed.getValue("value[1]"), 43)
|
||||
self.assertEqual(parsed.getValue("value[2]"), 44)
|
||||
|
||||
subNode = parsed.getChild("sub")
|
||||
widgets = subNode.getChildren("widget")
|
||||
self.assertEqual(len(widgets), 4)
|
||||
|
||||
self.assertEqual(widgets[2].value, 44)
|
||||
self.assertEqual(widgets[3].value, 99)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -9,6 +9,10 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import sgprops
|
||||
import sys
|
||||
import catalogTags
|
||||
import catalog
|
||||
|
||||
CATALOG_VERSION = 4
|
||||
|
||||
@@ -23,6 +27,8 @@ parser.add_argument("--clean", help="Force regeneration of all zip files",
|
||||
parser.add_argument("dir", help="Catalog directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
includes = []
|
||||
|
||||
# xml node (robust) get text helper
|
||||
def get_xml_text(e):
|
||||
if e != None and e.text != None:
|
||||
@@ -30,71 +36,6 @@ def get_xml_text(e):
|
||||
else:
|
||||
return ''
|
||||
|
||||
# create an xml node with text content
|
||||
def make_xml_leaf(name, text):
|
||||
leaf = ET.Element(name)
|
||||
if text != None:
|
||||
if isinstance(text, (int, long)):
|
||||
leaf.text = str(text)
|
||||
else:
|
||||
leaf.text = text
|
||||
else:
|
||||
leaf.text = ''
|
||||
return leaf
|
||||
|
||||
# return all available aircraft information from the set file as a
|
||||
# dict
|
||||
def scan_set_file(set_file):
|
||||
base_file = os.path.basename(set_file)
|
||||
base_id = base_file[:-8]
|
||||
#print ' scanning:', base_file
|
||||
parser = ET.XMLParser(remove_blank_text=True)
|
||||
set_xml = ET.parse(set_file, parser)
|
||||
set_node = set_xml.getroot()
|
||||
sim_node = set_node.find('sim')
|
||||
if sim_node == None:
|
||||
return None
|
||||
variant = {}
|
||||
variant['name'] = get_xml_text(sim_node.find('description'))
|
||||
variant['status'] = get_xml_text(sim_node.find('status'))
|
||||
variant['author'] = get_xml_text(sim_node.find('author'))
|
||||
variant['description'] = get_xml_text(sim_node.find('long-description'))
|
||||
variant['id'] = base_id
|
||||
rating_node = sim_node.find('rating')
|
||||
if rating_node != None:
|
||||
variant['rating_FDM'] = int(get_xml_text(rating_node.find('FDM')))
|
||||
variant['rating_systems'] = int(get_xml_text(rating_node.find('systems')))
|
||||
variant['rating_cockpit'] = int(get_xml_text(rating_node.find('cockpit')))
|
||||
variant['rating_model'] = int(get_xml_text(rating_node.find('model')))
|
||||
variant['variant-of'] = get_xml_text(sim_node.find('variant-of'))
|
||||
#print ' ', variant
|
||||
return variant
|
||||
|
||||
# scan all the -set.xml files in an aircraft directory. Returns a
|
||||
# package dict and a list of variants.
|
||||
def scan_aircraft_dir(aircraft_dir):
|
||||
found_master = False
|
||||
package = None
|
||||
variants = []
|
||||
files = os.listdir(aircraft_dir)
|
||||
for file in sorted(files, key=lambda s: s.lower()):
|
||||
if file.endswith('-set.xml'):
|
||||
variant = scan_set_file(os.path.join(aircraft_dir, file))
|
||||
if variant == None:
|
||||
continue
|
||||
if package == None:
|
||||
# just in case no one claims to be master, the first
|
||||
# variant defaults to master, but we will overwrite
|
||||
# this if we find something better.
|
||||
package = variant
|
||||
if not found_master and variant['variant-of'] == '':
|
||||
found_master = True
|
||||
package = variant
|
||||
else:
|
||||
variants.append( {'id': variant['id'],
|
||||
'name': variant['name'] } )
|
||||
return (package, variants)
|
||||
|
||||
# use svn commands to report the last change date within dir
|
||||
def last_change_date_svn(dir):
|
||||
command = [ 'svn', 'info', dir ]
|
||||
@@ -143,6 +84,117 @@ def get_md5sum(file):
|
||||
f.close()
|
||||
return md5sum
|
||||
|
||||
def copy_previews_for_variant(variant, package_name, package_dir, previews_dir):
|
||||
if not 'previews' in variant:
|
||||
return
|
||||
|
||||
for preview in variant['previews']:
|
||||
preview_src = os.path.join(package_dir, preview['path'])
|
||||
preview_dst = os.path.join(previews_dir, package_name + '_' + preview['path'])
|
||||
#print preview_src, preview_dst, preview['path']
|
||||
dir = os.path.dirname(preview_dst)
|
||||
if not os.path.isdir(dir):
|
||||
os.makedirs(dir)
|
||||
if os.path.exists(preview_src):
|
||||
shutil.copy2(preview_src, preview_dst)
|
||||
|
||||
def copy_previews_for_package(package, variants, package_name, package_dir, previews_dir):
|
||||
copy_previews_for_variant(package, package_name, package_dir, previews_dir)
|
||||
for v in variants:
|
||||
copy_previews_for_variant(v, package_name, package_dir, previews_dir)
|
||||
|
||||
def copy_thumbnail_for_variant(variant, package_name, package_dir, thumbnails_dir):
|
||||
if not 'thumbnail' in variant:
|
||||
return
|
||||
|
||||
thumb_src = os.path.join(package_dir, variant['thumbnail'])
|
||||
thumb_dst = os.path.join(thumbnails_dir, package_name + '_' + variant['thumbnail'])
|
||||
|
||||
dir = os.path.dirname(thumb_dst)
|
||||
if not os.path.isdir(dir):
|
||||
os.makedirs(dir)
|
||||
if os.path.exists(thumb_src):
|
||||
shutil.copy2(thumb_src, thumb_dst)
|
||||
|
||||
def copy_thumbnails_for_package(package, variants, package_name, package_dir, thumbnails_dir):
|
||||
copy_thumbnail_for_variant(package, package_name, package_dir, thumbnails_dir)
|
||||
|
||||
# and now each variant in turn
|
||||
for v in variants:
|
||||
copy_thumbnail_for_variant(v, package_name, package_dir, thumbnails_dir)
|
||||
|
||||
def process_aircraft_dir(name, repo_path):
|
||||
global includes
|
||||
global download_base
|
||||
global output_dir
|
||||
global valid_zips
|
||||
global previews_dir
|
||||
|
||||
aircraft_dir = os.path.join(repo_path, name)
|
||||
if not os.path.isdir(aircraft_dir):
|
||||
return
|
||||
|
||||
(package, variants) = catalog.scan_aircraft_dir(aircraft_dir, includes)
|
||||
if package == None:
|
||||
print "skipping:", name, "(no -set.xml files)"
|
||||
return
|
||||
|
||||
print "%s:" % name,
|
||||
|
||||
package_node = catalog.make_aircraft_node(name, package, variants, download_base)
|
||||
|
||||
download_url = download_base + name + '.zip'
|
||||
if 'thumbnail' in package:
|
||||
# this is never even used, but breaks the script by assuming
|
||||
# all aircraft packages have thumbnails defined?
|
||||
thumbnail_url = download_base + 'thumbnails/' + name + '_' + package['thumbnail']
|
||||
|
||||
# get cached md5sum if it exists
|
||||
md5sum = get_xml_text(md5sum_root.find(str('aircraft_' + name)))
|
||||
|
||||
# now do the packaging and rev number stuff
|
||||
dir_mtime = scan_dir_for_change_date_mtime(aircraft_dir)
|
||||
if repo_type == 'svn':
|
||||
rev = last_change_date_svn(aircraft_dir)
|
||||
else:
|
||||
d = datetime.datetime.utcfromtimestamp(dir_mtime)
|
||||
rev = d.strftime("%Y%m%d")
|
||||
package_node.append( catalog.make_xml_leaf('revision', rev) )
|
||||
#print "rev:", rev
|
||||
#print "dir mtime:", dir_mtime
|
||||
zipfile = os.path.join( output_dir, name + '.zip' )
|
||||
valid_zips.append(name + '.zip')
|
||||
if not os.path.exists(zipfile) \
|
||||
or dir_mtime > os.path.getmtime(zipfile) \
|
||||
or args.clean:
|
||||
# rebuild zip file
|
||||
print "updating:", zipfile
|
||||
make_aircraft_zip(repo_path, name, zipfile)
|
||||
md5sum = get_md5sum(zipfile)
|
||||
else:
|
||||
print "(no change)"
|
||||
if md5sum == "":
|
||||
md5sum = get_md5sum(zipfile)
|
||||
filesize = os.path.getsize(zipfile)
|
||||
package_node.append( catalog.make_xml_leaf('md5', md5sum) )
|
||||
package_node.append( catalog.make_xml_leaf('file-size-bytes', filesize) )
|
||||
|
||||
# handle md5sum cache
|
||||
node = md5sum_root.find('aircraft_' + name)
|
||||
if node != None:
|
||||
node.text = md5sum
|
||||
else:
|
||||
md5sum_root.append( catalog.make_xml_leaf('aircraft_' + name, md5sum) )
|
||||
|
||||
# handle thumbnails
|
||||
copy_thumbnails_for_package(package, variants, name, aircraft_dir, thumbnail_dir)
|
||||
|
||||
catalog_node.append(package_node)
|
||||
|
||||
# copy previews for the package and variants into the
|
||||
# output directory
|
||||
copy_previews_for_package(package, variants, name, aircraft_dir, previews_dir)
|
||||
|
||||
#def get_file_stats(file):
|
||||
# f = open(file, 'r')
|
||||
# md5 = hashlib.md5(f.read()).hexdigest()
|
||||
@@ -175,17 +227,33 @@ else:
|
||||
scm_list = config_node.findall('scm')
|
||||
upload_node = config_node.find('upload')
|
||||
download_base = get_xml_text(config_node.find('download-url'))
|
||||
if not download_base.endswith('/'):
|
||||
download_base += '/'
|
||||
|
||||
output_dir = get_xml_text(config_node.find('local-output'))
|
||||
if output_dir == '':
|
||||
output_dir = os.path.join(args.dir, 'output')
|
||||
if not os.path.isdir(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
|
||||
thumbnail_dir = os.path.join(output_dir, 'thumbnails')
|
||||
if not os.path.isdir(thumbnail_dir):
|
||||
os.mkdir(thumbnail_dir)
|
||||
|
||||
previews_dir = os.path.join(output_dir, 'previews')
|
||||
if not os.path.isdir(previews_dir):
|
||||
os.mkdir(previews_dir)
|
||||
|
||||
tmp = os.path.join(args.dir, 'zip-excludes.lst')
|
||||
zip_excludes = os.path.realpath(tmp)
|
||||
|
||||
for i in config_node.findall("include-dir"):
|
||||
path = get_xml_text(i)
|
||||
if not os.path.exists(path):
|
||||
print "Skipping missing include path:", path
|
||||
continue
|
||||
includes.append(path)
|
||||
|
||||
# freshen repositories
|
||||
if args.no_update:
|
||||
print 'Skipping repository updates.'
|
||||
@@ -194,6 +262,8 @@ else:
|
||||
for scm in scm_list:
|
||||
repo_type = get_xml_text(scm.find('type'))
|
||||
repo_path = get_xml_text(scm.find('path'))
|
||||
includes.append(repo_path)
|
||||
|
||||
if repo_type == 'svn':
|
||||
print 'SVN update:', repo_path
|
||||
subprocess.call(['svn', 'update', repo_path])
|
||||
@@ -232,92 +302,10 @@ for scm in scm_list:
|
||||
if name in skip_list:
|
||||
print "skipping:", name
|
||||
continue
|
||||
aircraft_dir = os.path.join(repo_path, name)
|
||||
if os.path.isdir(aircraft_dir):
|
||||
print "%s:" % name,
|
||||
(package, variants) = scan_aircraft_dir(aircraft_dir)
|
||||
if package == None:
|
||||
print "skipping:", name, "(no -set.xml files)"
|
||||
continue
|
||||
#print "package:", package
|
||||
#print "variants:", variants
|
||||
package_node = ET.Element('package')
|
||||
package_node.append( make_xml_leaf('name', package['name']) )
|
||||
package_node.append( make_xml_leaf('status', package['status']) )
|
||||
package_node.append( make_xml_leaf('author', package['author']) )
|
||||
package_node.append( make_xml_leaf('description', package['description']) )
|
||||
if 'rating_FDM' in package or 'rating_systems' in package \
|
||||
or 'rating_cockpit' in package or 'rating_model' in package:
|
||||
rating_node = ET.Element('rating')
|
||||
package_node.append(rating_node)
|
||||
rating_node.append( make_xml_leaf('FDM',
|
||||
package['rating_FDM']) )
|
||||
rating_node.append( make_xml_leaf('systems',
|
||||
package['rating_systems']) )
|
||||
rating_node.append( make_xml_leaf('cockpit',
|
||||
package['rating_cockpit']) )
|
||||
rating_node.append( make_xml_leaf('model',
|
||||
package['rating_model']) )
|
||||
package_node.append( make_xml_leaf('id', package['id']) )
|
||||
for variant in variants:
|
||||
variant_node = ET.Element('variant')
|
||||
package_node.append(variant_node)
|
||||
variant_node.append( make_xml_leaf('id', variant['id']) )
|
||||
variant_node.append( make_xml_leaf('name', variant['name']) )
|
||||
package_node.append( make_xml_leaf('dir', name) )
|
||||
if not download_base.endswith('/'):
|
||||
download_base += '/'
|
||||
download_url = download_base + name + '.zip'
|
||||
thumbnail_url = download_base + 'thumbnails/' + name + '_thumbnail.jpg'
|
||||
package_node.append( make_xml_leaf('url', download_url) )
|
||||
package_node.append( make_xml_leaf('thumbnail', thumbnail_url) )
|
||||
|
||||
# todo: url (download), thumbnail (download url)
|
||||
|
||||
# get cached md5sum if it exists
|
||||
md5sum = get_xml_text(md5sum_root.find(str('aircraft_' + name)))
|
||||
|
||||
# now do the packaging and rev number stuff
|
||||
dir_mtime = scan_dir_for_change_date_mtime(aircraft_dir)
|
||||
if repo_type == 'svn':
|
||||
rev = last_change_date_svn(aircraft_dir)
|
||||
else:
|
||||
d = datetime.datetime.utcfromtimestamp(dir_mtime)
|
||||
rev = d.strftime("%Y%m%d")
|
||||
package_node.append( make_xml_leaf('revision', rev) )
|
||||
#print "rev:", rev
|
||||
#print "dir mtime:", dir_mtime
|
||||
zipfile = os.path.join( output_dir, name + '.zip' )
|
||||
valid_zips.append(name + '.zip')
|
||||
if not os.path.exists(zipfile) \
|
||||
or dir_mtime > os.path.getmtime(zipfile) \
|
||||
or args.clean:
|
||||
# rebuild zip file
|
||||
print "updating:", zipfile
|
||||
make_aircraft_zip(repo_path, name, zipfile)
|
||||
md5sum = get_md5sum(zipfile)
|
||||
else:
|
||||
print "(no change)"
|
||||
if md5sum == "":
|
||||
md5sum = get_md5sum(zipfile)
|
||||
filesize = os.path.getsize(zipfile)
|
||||
package_node.append( make_xml_leaf('md5', md5sum) )
|
||||
package_node.append( make_xml_leaf('file-size-bytes', filesize) )
|
||||
|
||||
# handle md5sum cache
|
||||
node = md5sum_root.find('aircraft_' + name)
|
||||
if node != None:
|
||||
node.text = md5sum
|
||||
else:
|
||||
md5sum_root.append( make_xml_leaf('aircraft_' + name, md5sum) )
|
||||
|
||||
# handle thumbnails
|
||||
thumbnail_src = os.path.join(aircraft_dir, 'thumbnail.jpg')
|
||||
thumbnail_dst = os.path.join(thumbnail_dir, name + '_thumbnail.jpg')
|
||||
if os.path.exists(thumbnail_src):
|
||||
shutil.copy2(thumbnail_src, thumbnail_dst)
|
||||
catalog_node.append(package_node)
|
||||
package_node.append( make_xml_leaf('thumbnail-path', 'thumbnail.jpg') )
|
||||
# process each aircraft in turn
|
||||
# print name, repo_path
|
||||
process_aircraft_dir(name, repo_path)
|
||||
|
||||
# write out the master catalog file
|
||||
cat_file = os.path.join(output_dir, 'catalog.xml')
|
||||
@@ -332,4 +320,3 @@ files = os.listdir(output_dir)
|
||||
for file in files:
|
||||
if file.endswith('.zip')and not file in valid_zips:
|
||||
print "orphaned zip:", file
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
aircraftTypeTags = [
|
||||
"ga", "fighter", "helicopter", "glider", "spaceship", "bomber", "groundvehicle",
|
||||
"tanker", "cargo", "transport", "bizjet", "trainer", "airship", "balloon"
|
||||
]
|
||||
|
||||
manufacturerTags = [
|
||||
"boeing", "cessna", "diamond", "douglas", "bell", "piper",
|
||||
"airbus", "vickers", "lockheed", "fokker",
|
||||
"embraer", "bombardier", "pilatus", "robin",
|
||||
"eurocopter"
|
||||
]
|
||||
|
||||
eraTags = [
|
||||
"early-pioneers",
|
||||
"ww1",
|
||||
"1920s",
|
||||
"1930s",
|
||||
"golden-age",
|
||||
"ww2",
|
||||
"coldwar", "vietnam",
|
||||
"1950s",
|
||||
"1960s",
|
||||
"1970s",
|
||||
"1980s",
|
||||
"1990s",
|
||||
"2000s",
|
||||
"gulfwar1",
|
||||
"gulfwar2"
|
||||
]
|
||||
|
||||
featureTags = [
|
||||
"ifr",
|
||||
"retractable-gear",
|
||||
"fixed-gear",
|
||||
"tail-dragger",
|
||||
"seaplane",
|
||||
"vtol",
|
||||
"stol",
|
||||
"experimental",
|
||||
"prototype",
|
||||
"fictional",
|
||||
"biplane",
|
||||
"triplane",
|
||||
"supersonic",
|
||||
"t-tail",
|
||||
"v-tail",
|
||||
"high-wing",
|
||||
"cannard",
|
||||
"tail-hook",
|
||||
"refuel",
|
||||
"delta",
|
||||
"variable-geometry",
|
||||
"glass-cockpit",
|
||||
"hud",
|
||||
"etops",
|
||||
"floats",
|
||||
"amphibious",
|
||||
"airship",
|
||||
"aerobatic"
|
||||
]
|
||||
|
||||
propulsionTags = [
|
||||
"piston", "radial",
|
||||
"diesel",
|
||||
"variable-pitch",
|
||||
"supercharged",
|
||||
"turboprop",
|
||||
"jet", "afterburner", "rocket",
|
||||
"electric",
|
||||
"twin-engine",
|
||||
"single-engine"
|
||||
]
|
||||
|
||||
simFeatureTags = [
|
||||
"tow",
|
||||
"dual-controls",
|
||||
"rembrandt"
|
||||
]
|
||||
|
||||
tags = aircraftTypeTags + manufacturerTags + eraTags + simFeatureTags + propulsionTags + featureTags
|
||||
@@ -0,0 +1,9 @@
|
||||
--- apt.dat 2016-12-08 18:43:50.000000000 +0100
|
||||
+++ apt.dat-000 2016-12-08 18:56:02.310707492 +0100
|
||||
@@ -1,5 +1,5 @@
|
||||
I
|
||||
-1000 Version - data cycle 2013.10, build 20131335, metadata AptXP1000. Copyright <20> 2013, Robin A. Peel (robin@x-plane.com). This data is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program ("AptNavGNULicence.txt"); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
+1000 Version - data cycle 2013.10, build 20131335, metadata AptXP1000, further modified by the FlightGear team (cf. <https://sourceforge.net/p/flightgear/fgmeta/ci/next/tree/changes-in-dat-files/apt.dat>). Copyright <20> 2013, Robin A. Peel (robin@x-plane.com). This data is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program ("AptNavGNULicence.txt"); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
1 15 1 0 VHXX [X] CLOSED Kai Tak
|
||||
@@ -0,0 +1,11 @@
|
||||
--- apt.dat 2016-12-08 18:56:02.310707492 +0100
|
||||
+++ apt.dat-001 2016-12-08 19:01:00.082169377 +0100
|
||||
@@ -926129,7 +926129,7 @@
|
||||
19 45.98520090 -065.30815534 1 WS
|
||||
19 45.98509598 -065.29620316 1 WS
|
||||
19 45.98776000 -065.29826459 1 WS
|
||||
-51 12320
|
||||
+51 12320 CTAF/UNICOM
|
||||
|
||||
1 1000 0 1 3MN7 Haven
|
||||
100 22.86 3 0 0.25 0 0 0 15 45.49243037 -094.12309108 0.00 0.00 1 0 0 0 33 45.48749963 -094.11966060 0.00 0.00 1 0 0 0
|
||||
21
compile-scripts/README.md
Normal file
21
compile-scripts/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
This is the scripts I (James) use to maintain my builds on each platform.
|
||||
|
||||
They're much less clever than 'download and compile' but they do enough for me
|
||||
and probably most other people, if you tweak the paths accordingly. The Mac
|
||||
and Linux ones require Ruby (which is usually pre-installed). There are no
|
||||
instructions - if you can't figure out what these do from reading the scripts,
|
||||
you almost certainly should not be using them!
|
||||
|
||||
They all assume a top-level folder which contains
|
||||
checkouts of simgear, flightgear, fgdata, OpenSceneGraph (into a dir named
|
||||
'osg') and the windows-3rd-party dir in the case of Windows. It's assumed
|
||||
you copy the script to that same dir, edit paths and run from there.
|
||||
|
||||
The Mac and Linux scripts will do the checkout for you - the Windows is not
|
||||
so smart because Window batch scripts are not my friend.
|
||||
|
||||
On Mac you will need to grab the 3rdparty-dependency-build from Jenkins, or
|
||||
build PLIB manually yourself, either should be straightforward. For all other
|
||||
dependencies on Mac / Linux use your package manager / Homebrew.
|
||||
|
||||
Files will be installed into a subdir called 'dist'
|
||||
130
compile-scripts/commands-linux.rb
Executable file
130
compile-scripts/commands-linux.rb
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'fileutils'
|
||||
require 'optparse'
|
||||
include FileUtils
|
||||
|
||||
baseDir = Dir.pwd
|
||||
gitArgs = ""
|
||||
qtPath = ""
|
||||
|
||||
doPull = false
|
||||
doCMake = false
|
||||
doInit = false
|
||||
doClean = false
|
||||
doPackage = false
|
||||
|
||||
cmakeCommonArgs = "-DCMAKE_INSTALL_PREFIX=#{baseDir}/dist -DSIMGEAR_SHARED=1"
|
||||
cmakeFGArgs = ""
|
||||
sfUser = "jmturner"
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Usage: commands.rb [options]"
|
||||
opts.on("", "--init", "Setup empty") do |v|
|
||||
doInit = v
|
||||
end
|
||||
|
||||
opts.on("-p", "--[no-]pull", "Pull from Git") do |v|
|
||||
doPull = v
|
||||
end
|
||||
opts.on("-c", "--cmake", "Run Cmake") do |v|
|
||||
doCMake = v
|
||||
end
|
||||
opts.on("", "--clean", "Clean build dirs") do |v|
|
||||
doClean = v
|
||||
end
|
||||
opts.on("-r", "--rebase", "Rebase when pulling") do |v|
|
||||
gitArgs += "--rebase"
|
||||
end
|
||||
|
||||
opts.on("", "--qt=QTPATH", "Set Qt path when running cmake") do |v|
|
||||
qtPath = v
|
||||
end
|
||||
end.parse!(ARGV)
|
||||
|
||||
def cloneEverything()
|
||||
puts "Initialising"
|
||||
if File.exist?("#{Dir.pwd}/simgear") or File.exist?("#{Dir.pwd}/flightgear")
|
||||
puts "Checkout already exists"
|
||||
return
|
||||
end
|
||||
|
||||
`git clone ssh://#{sfUser}@git.code.sf.net/p/flightgear/simgear simgear`
|
||||
`git clone ssh://#{sfUser}@git.code.sf.net/p/flightgear/flightgear flightgear`
|
||||
`git clone ssh://#{sfUser}@git.code.sf.net/p/flightgear/fgdata fgdata`
|
||||
`git clone https://github.com/openscenegraph/osg.git osg`
|
||||
end
|
||||
|
||||
def createDirs()
|
||||
`mkdir -p sgbuild`
|
||||
`mkdir -p fgbuild`
|
||||
`mkdir -p osg_release_build`
|
||||
end
|
||||
|
||||
# path is needed for Cmake & running macdeployqt
|
||||
if qtPath != ""
|
||||
ENV['PATH'] = "#{ENV['PATH']}:#{qtPath}/bin"
|
||||
end
|
||||
|
||||
if doClean
|
||||
puts "Cleaning build dirs"
|
||||
`rm -r sgbuild`
|
||||
`rm -r fgbuild`
|
||||
`rm -r osg_release_build`
|
||||
createDirs()
|
||||
end
|
||||
|
||||
if doInit
|
||||
puts "Doing init"
|
||||
cloneEverything()
|
||||
createDirs();
|
||||
end
|
||||
|
||||
if doPull
|
||||
puts "Pulling from Git"
|
||||
dataPull = Thread.new do
|
||||
puts "Syncing FGData"
|
||||
Dir.chdir "#{baseDir}/fgdata"
|
||||
`git pull #{gitArgs}`
|
||||
end
|
||||
|
||||
Dir.chdir "#{baseDir}/simgear"
|
||||
`git pull #{gitArgs}`
|
||||
|
||||
Dir.chdir "#{baseDir}/flightgear"
|
||||
`git pull #{gitArgs}`
|
||||
end
|
||||
|
||||
Dir.chdir "#{baseDir}/osg_release_build"
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/Makefile")
|
||||
`cmake ../osg -DCMAKE_INSTALL_PREFIX=#{baseDir}/dist`
|
||||
end
|
||||
|
||||
puts "Building OpenSceneGraph"
|
||||
`make`
|
||||
`make install`
|
||||
|
||||
Dir.chdir "#{baseDir}/sgbuild"
|
||||
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/Makefile")
|
||||
`cmake ../simgear #{cmakeCommonArgs}`
|
||||
end
|
||||
|
||||
puts "Building SimGear"
|
||||
`make`
|
||||
`make install`
|
||||
|
||||
Dir.chdir "#{baseDir}/fgbuild"
|
||||
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/Makefile")
|
||||
if qtPath != ""
|
||||
cmakeFGArgs = '-DENABLE_QT=1'
|
||||
end
|
||||
`cmake ../flightgear #{cmakeCommonArgs} #{cmakeFGArgs}`
|
||||
end
|
||||
|
||||
puts "Building FlightGear"
|
||||
`make`
|
||||
`make install`
|
||||
|
||||
puts "All done."
|
||||
135
compile-scripts/commands-mac.rb
Executable file
135
compile-scripts/commands-mac.rb
Executable file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'fileutils'
|
||||
require 'optparse'
|
||||
include FileUtils
|
||||
|
||||
baseDir = Dir.pwd
|
||||
gitArgs = ""
|
||||
qtPath = ""
|
||||
|
||||
doPull = false
|
||||
doCMake = false
|
||||
doInit = false
|
||||
doClean = false
|
||||
doPackage = false
|
||||
|
||||
cmakePlatformArgs = "-G Xcode"
|
||||
cmakeCommonArgs = "-DCMAKE_INSTALL_PREFIX=#{baseDir}/dist"
|
||||
cmakeSGArgs = "-DSIMGEAR_SHARED=1"
|
||||
cmakeFGArgs = "-DSIMGEAR_SHARED=1"
|
||||
sfUser = "jmturner"
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Usage: commands.rb [options]"
|
||||
opts.on("", "--init", "Setup empty") do |v|
|
||||
doInit = v
|
||||
end
|
||||
|
||||
opts.on("-p", "--[no-]pull", "Pull from Git") do |v|
|
||||
doPull = v
|
||||
end
|
||||
opts.on("-c", "--cmake", "Run Cmake") do |v|
|
||||
doCMake = v
|
||||
end
|
||||
opts.on("", "--clean", "Clean build dirs") do |v|
|
||||
doClean = v
|
||||
end
|
||||
opts.on("-r", "--rebase", "Rebase when pulling") do |v|
|
||||
gitArgs += "--rebase"
|
||||
end
|
||||
|
||||
opts.on("", "--qt=QTPATH", "Set Qt path when running cmake") do |v|
|
||||
qtPath = v
|
||||
end
|
||||
end.parse!(ARGV)
|
||||
|
||||
def cloneEverything()
|
||||
puts "Initialising"
|
||||
if File.exist?("#{Dir.pwd}/simgear") or File.exist?("#{Dir.pwd}/flightgear")
|
||||
puts "Checkout already exists"
|
||||
return
|
||||
end
|
||||
|
||||
`git clone ssh://#{sfUser}@git.code.sf.net/p/flightgear/simgear simgear`
|
||||
`git clone ssh://#{sfUser}@git.code.sf.net/p/flightgear/flightgear flightgear`
|
||||
`git clone git@github.com:zakalawe/osg.git osg`
|
||||
end
|
||||
|
||||
def createDirs()
|
||||
`mkdir -p sgbuild`
|
||||
`mkdir -p fgbuild`
|
||||
`mkdir -p osg_fg_build`
|
||||
end
|
||||
|
||||
# path is needed for Cmake & running macdeployqt
|
||||
if qtPath != ""
|
||||
ENV['PATH'] = "#{ENV['PATH']}:#{qtPath}/bin"
|
||||
end
|
||||
|
||||
if doClean
|
||||
puts "Cleaning build dirs"
|
||||
`rm -r sgbuild`
|
||||
`rm -r fgbuild`
|
||||
`rm -r osg_fg_build`
|
||||
end
|
||||
|
||||
if doInit
|
||||
puts "Doing init"
|
||||
cloneEverything()
|
||||
end
|
||||
|
||||
if doPull
|
||||
puts "Pulling from Git"
|
||||
dataPull = Thread.new do
|
||||
puts "Syncing FGData"
|
||||
Dir.chdir "#{baseDir}/fgdata"
|
||||
`git pull #{gitArgs}`
|
||||
end
|
||||
|
||||
Dir.chdir "#{baseDir}/simgear"
|
||||
`git pull #{gitArgs}`
|
||||
|
||||
Dir.chdir "#{baseDir}/flightgear"
|
||||
`git pull #{gitArgs}`
|
||||
end
|
||||
|
||||
createDirs()
|
||||
|
||||
Dir.chdir "#{baseDir}/osg_fg_build"
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/Makefile")
|
||||
`cmake ../osg #{cmakeCommonArgs}`
|
||||
end
|
||||
|
||||
puts "Building OpenSceneGraph"
|
||||
`make -j4`
|
||||
`make install`
|
||||
|
||||
Dir.chdir "#{baseDir}/sgbuild"
|
||||
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/SimGear.xcodeproj")
|
||||
`cmake ../simgear #{cmakePlatformArgs} #{cmakeCommonArgs} #{cmakeSGArgs}`
|
||||
end
|
||||
|
||||
puts "Building SimGear Debug"
|
||||
`xcodebuild -target install -configuration Debug`
|
||||
|
||||
puts "Building SimGear Release"
|
||||
`xcodebuild -target install -configuration Release`
|
||||
|
||||
Dir.chdir "#{baseDir}/fgbuild"
|
||||
|
||||
if doCMake or !File.exist?("#{Dir.pwd}/FlightGear.xcodeproj")
|
||||
if qtPath != ""
|
||||
cmakeFGArgs = '-DENABLE_QT=1'
|
||||
end
|
||||
`cmake ../flightgear #{cmakePlatformArgs} #{cmakeCommonArgs} #{cmakeFGArgs}`
|
||||
end
|
||||
|
||||
puts "Building FlightGear Debug"
|
||||
`xcodebuild -target fgfs -configuration Debug`
|
||||
|
||||
puts "Building FlightGear Release"
|
||||
`xcodebuild -target fgfs -configuration Release`
|
||||
|
||||
puts "All done."
|
||||
52
compile-scripts/pull_build.bat
Normal file
52
compile-scripts/pull_build.bat
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
SET PATH=%PATH%;%ProgramFiles%\CMake\bin
|
||||
SET QT5SDK64=C:\Qt\5.6\msvc2015_64
|
||||
SET CMAKE_TOOLCHAIN="Visual Studio 14 Win64"
|
||||
SET ROOT_DIR=%CD%
|
||||
|
||||
md osgbuild
|
||||
md sgbuild
|
||||
md fgbuild
|
||||
REM md fgrun-build
|
||||
|
||||
cd simgear
|
||||
git pull --rebase
|
||||
|
||||
cd ..\flightgear
|
||||
git pull --rebase
|
||||
|
||||
REM cd ..\fgrun
|
||||
REM git pull --rebase
|
||||
|
||||
cd ..\osgbuild
|
||||
cmake ..\osg -G %CMAKE_TOOLCHAIN% ^
|
||||
-DACTUAL_3RDPARTY_DIR:PATH=%ROOT_DIR%\windows-3rd-party\msvc140\3rdparty.x64 ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\dist ^
|
||||
-DOSG_USE_UTF8_FILENAME:BOOL=ON
|
||||
|
||||
cmake --build . --config Release --target INSTALL
|
||||
cmake --build . --config Debug --target INSTALL
|
||||
|
||||
cd ..\sgbuild
|
||||
cmake ..\simgear -G %CMAKE_TOOLCHAIN% ^
|
||||
-DMSVC_3RDPARTY_ROOT=%ROOT_DIR%\windows-3rd-party\msvc140 ^
|
||||
-DOSG_FSTREAM_EXPORT_FIXED:BOOL=ON ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\dist
|
||||
cmake --build . --config Release --target INSTALL
|
||||
cmake --build . --config Debug --target INSTALL
|
||||
|
||||
cd ..\fgbuild
|
||||
cmake ..\flightgear -G %CMAKE_TOOLCHAIN% ^
|
||||
-DMSVC_3RDPARTY_ROOT=%ROOT_DIR%\windows-3rd-party\msvc140 ^
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\dist ^
|
||||
-DCMAKE_PREFIX_PATH=%QT5SDK64% ^
|
||||
-DOSG_FSTREAM_EXPORT_FIXED:BOOL=ON
|
||||
cmake --build . --config Release --target INSTALL
|
||||
cmake --build . --config Debug --target INSTALL
|
||||
|
||||
REM cd ..\fgrun-build
|
||||
REM cmake ..\fgrun -G %CMAKE_TOOLCHAIN% ^
|
||||
REM -DMSVC_3RDPARTY_ROOT=C:\FGFS\windows-3rd-party\msvc140 ^
|
||||
REM -DCMAKE_INSTALL_PREFIX:PATH=C:\FGFS\dist
|
||||
REM cmake --build . --config Release --target INSTALL
|
||||
REM cmake --build . --config Debug --target INSTALL
|
||||
@@ -17,8 +17,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
VERSION="2.33"
|
||||
FGVERSION="release/$(git ls-remote --heads git://git.code.sf.net/p/flightgear/flightgear|grep '\/release\/'|cut -f4 -d'/'|sort -t . -k 1,1n -k2,2n -k3,3n|tail -1)"
|
||||
script_blob_id='$Id$'
|
||||
# Slightly tricky substitution to avoid our regexp being wildly replaced with
|
||||
# the blob name (id) when the script is checked out:
|
||||
#
|
||||
# First extract the hexadecimal blob object name followed by a '$'
|
||||
VERSION="$(echo "$script_blob_id" | sed 's@\$Id: *\([0-9a-f]\+\) *@\1@')"
|
||||
# Then remove the trailing '$'
|
||||
VERSION="${VERSION%\$}"
|
||||
|
||||
PROGNAME=$(basename "$0")
|
||||
FGVERSION="release/$(git ls-remote --heads https://git.code.sf.net/p/flightgear/flightgear|grep '\/release\/'|cut -f4 -d'/'|sort -t . -k 1,1n -k2,2n -k3,3n|tail -1)"
|
||||
|
||||
#######################################################
|
||||
# THANKS TO
|
||||
@@ -32,7 +41,7 @@ FGVERSION="release/$(git ls-remote --heads git://git.code.sf.net/p/flightgear/fl
|
||||
|
||||
LOGFILE=compilation_log.txt
|
||||
WHATTOBUILD=
|
||||
#AVAILABLE VALUES: PLIB OPENRTI OSG SIMGEAR FGFS DATA FGRUN FGO FGX OPENRADAR ATCPIE TERRAGEAR TERRAGEARGUI
|
||||
#AVAILABLE VALUES: CMAKE PLIB OPENRTI OSG SIMGEAR FGFS DATA FGRUN FGO FGX OPENRADAR ATCPIE TERRAGEAR TERRAGEARGUI
|
||||
WHATTOBUILDALL=(SIMGEAR FGFS DATA)
|
||||
STABLE=
|
||||
APT_GET_UPDATE="y"
|
||||
@@ -42,11 +51,13 @@ RECONFIGURE="y"
|
||||
DOWNLOAD="y"
|
||||
JOPTION=""
|
||||
OOPTION=""
|
||||
DEBUG=""
|
||||
BUILD_TYPE="RelWithDebInfo"
|
||||
SG_CMAKEARGS=""
|
||||
FG_CMAKEARGE=""
|
||||
FG_CMAKEARGS=""
|
||||
|
||||
while getopts "shc:p:a:d:r:j:O:i" OPTION; do
|
||||
declare -a UNMATCHED_OPTIONAL_PKG_ALTERNATIVES
|
||||
|
||||
while getopts "shc:p:a:d:r:j:O:ib:" OPTION; do
|
||||
case $OPTION in
|
||||
s) STABLE="STABLE" ;;
|
||||
h) HELP="HELP" ;;
|
||||
@@ -58,6 +69,7 @@ while getopts "shc:p:a:d:r:j:O:i" OPTION; do
|
||||
j) JOPTION=" -j"$OPTARG" " ;;
|
||||
O) OOPTION=" -O"$OPTARG" " ;;
|
||||
i) OPENRTI="OPENRTI" ;;
|
||||
b) BUILD_TYPE="$OPTARG" ;;
|
||||
?) HELP="HELP" ;;
|
||||
esac
|
||||
done
|
||||
@@ -85,8 +97,8 @@ fi
|
||||
|
||||
|
||||
if [ "$OPENRTI" = "OPENRTI" ]; then
|
||||
SG_CMAKEARGS="$SG_CMAKEARGS-DENABLE_RTI=ON;"
|
||||
FG_CMAKEARGS="$FG_CMAKEARGS-DENABLE_RTI=ON;"
|
||||
SG_CMAKEARGS="$SG_CMAKEARGS -DENABLE_RTI=ON;"
|
||||
FG_CMAKEARGS="$FG_CMAKEARGS -DENABLE_RTI=ON;"
|
||||
WHATTOBUILD=( "${WHATTOBUILD[@]}" OPENRTI )
|
||||
fi
|
||||
|
||||
@@ -99,6 +111,16 @@ function _logSep(){
|
||||
echo "***********************************" >> $LOGFILE
|
||||
}
|
||||
|
||||
function _aptUpdate(){
|
||||
echo "Asking password for 'apt-get update'..."
|
||||
sudo apt-get update
|
||||
}
|
||||
|
||||
function _aptInstall(){
|
||||
echo "Asking password for 'apt-get install $*'..."
|
||||
sudo apt-get install "$@"
|
||||
}
|
||||
|
||||
function _gitUpdate(){
|
||||
if [ "$DOWNLOAD" != "y" ]; then
|
||||
return
|
||||
@@ -108,13 +130,13 @@ function _gitUpdate(){
|
||||
git diff --exit-code 2>&1 > /dev/null
|
||||
if [ $? != 1 ]; then
|
||||
set -e
|
||||
git checkout -f $branch
|
||||
git pull -r
|
||||
git checkout -f $branch
|
||||
else
|
||||
set -e
|
||||
git stash save -u -q
|
||||
git checkout -f $branch
|
||||
git pull -r
|
||||
git checkout -f $branch
|
||||
git stash pop -q
|
||||
fi
|
||||
}
|
||||
@@ -124,7 +146,7 @@ function _gitDownload(){
|
||||
return
|
||||
fi
|
||||
repo=$1
|
||||
if [ -f "README" -o -f "README.txt" ]; then
|
||||
if [ -f "README" -o -f "README.txt" -o -f "README.rst" ]; then
|
||||
echo "$repo exists already"
|
||||
else
|
||||
git clone $repo .
|
||||
@@ -142,6 +164,90 @@ function _make(){
|
||||
fi
|
||||
}
|
||||
|
||||
# Add an available, non-virtual package matching one of the given regexps.
|
||||
#
|
||||
# Each positional parameter is interpreted as a POSIX extended regular
|
||||
# expression. These parameters are examined from left to right, and the first
|
||||
# available matching package is added to the global PKG variable. If no match
|
||||
# is found, the script aborts.
|
||||
function _mandatory_pkg_alternative(){
|
||||
local pkg
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Empty package alternative: this is a bug in the script, aborting." \
|
||||
| tee -a "$LOGFILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Considering a package alternative:" "$@" | tee -a "$LOGFILE"
|
||||
pkg=$(_find_package_alternative "$@")
|
||||
|
||||
if [[ -n "$pkg" ]]; then
|
||||
echo "Package alternative matched for $pkg" | tee -a "$LOGFILE"
|
||||
PKG="$PKG $pkg"
|
||||
else
|
||||
echo "No match found for the package alternative, aborting." \
|
||||
| tee -a "$LOGFILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# If available, add a non-virtual package matching one of the given regexps.
|
||||
#
|
||||
# Returning 0 or 1 on success to indicate whether a match was found could be
|
||||
# done, but would need to be specifically handled at the calling site,
|
||||
# since the script is run under 'set -e' regime.
|
||||
function _optional_pkg_alternative(){
|
||||
local pkg
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Empty optional package alternative: this is a bug in the script," \
|
||||
"aborting." | tee -a "$LOGFILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Considering an optional package alternative:" "$@" | tee -a "$LOGFILE"
|
||||
pkg=$(_find_package_alternative "$@")
|
||||
|
||||
if [[ -n "$pkg" ]]; then
|
||||
echo "Optional package alternative matched for $pkg" | tee -a "$LOGFILE"
|
||||
PKG="$PKG $pkg"
|
||||
else
|
||||
echo "No match found for the optional package alternative, continuing" \
|
||||
"anyway." | tee -a "$LOGFILE"
|
||||
# "$*" so that we only add one element to the array in this line
|
||||
UNMATCHED_OPTIONAL_PKG_ALTERNATIVES+=("$*")
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# This function requires the 'dctrl-tools' package
|
||||
function _find_package_alternative(){
|
||||
local pkg
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
return 0 # Nothing could be found
|
||||
fi
|
||||
|
||||
# This finds non-virtual packages only (on purpose)
|
||||
pkg="$(apt-cache dumpavail | \
|
||||
grep-dctrl -e -sPackage -FPackage \
|
||||
"^[[:space:]]*($1)[[:space:]]*\$" - | \
|
||||
sed -ne '1s/^Package:[[:space:]]*//gp')"
|
||||
|
||||
if [[ -n "$pkg" ]]; then
|
||||
echo "$pkg"
|
||||
return 0
|
||||
else
|
||||
# Try with the next regexp
|
||||
shift
|
||||
_find_package_alternative "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################################
|
||||
# set script to stop if an error occours
|
||||
set -e
|
||||
@@ -149,14 +255,14 @@ set -e
|
||||
if [ "$HELP" = "HELP" ]; then
|
||||
echo "$0 Version $VERSION"
|
||||
echo "Usage:"
|
||||
echo "./$0 [-h] [-s] [-e] [-f] [-i] [-g] [-a y|n] [-c y|n] [-p y|n] [-d y|n] [-r y|n] [ALL|PLIB|OPENRTI|SIMGEAR|FGFS|DATA|FGRUN|FGO|FGX|OPENRADAR|ATCPIE|TERRAGEAR|TERRAGEARGUI]"
|
||||
echo "./$0 [-h] [-s] [-e] [-f] [-i] [-g] [-a y|n] [-c y|n] [-p y|n] [-d y|n] [-r y|n] [ALL|CMAKE|OSG|PLIB|OPENRTI|SIMGEAR|FGFS|DATA|FGRUN|FGO|FGX|OPENRADAR|ATCPIE|TERRAGEAR|TERRAGEARGUI]"
|
||||
echo "* without options or with ALL it recompiles the content of the WHATTOBUILDALL variable."
|
||||
echo "* Feel you free to customize the WHATTOBUILDALL variable available on the top of this script"
|
||||
echo "Switches:"
|
||||
echo "* -h show this help"
|
||||
echo "* -e compile FlightGear with --with-eventinput option (experimental)"
|
||||
echo "* -i compile SimGear and FlightGear with -D ENABLE_RTI=ON option (experimental)"
|
||||
echo "* -g compile with debug info for gcc"
|
||||
echo "* -b Release|RelWithDebInfo|Debug set build type default=RelWithDebInfo"
|
||||
echo "* -a y|n y=do an apt-get update n=skip apt-get update default=y"
|
||||
echo "* -p y|n y=download packages n=skip download packages default=y"
|
||||
echo "* -c y|n y=compile programs n=do not compile programs default=y"
|
||||
@@ -195,21 +301,52 @@ echo "RECONFIGURE=$RECONFIGURE" >> $LOGFILE
|
||||
echo "DOWNLOAD=$DOWNLOAD" >> $LOGFILE
|
||||
echo "JOPTION=$JOPTION" >> $LOGFILE
|
||||
echo "OOPTION=$OOPTION" >> $LOGFILE
|
||||
echo "DEBUG=$DEBUG" >> $LOGFILE
|
||||
echo "BUILD_TYPE=$BUILD_TYPE" >> $LOGFILE
|
||||
_logSep
|
||||
|
||||
#######################################################
|
||||
#######################################################
|
||||
|
||||
if [[ "$DOWNLOAD_PACKAGES" = "y" ]] && [[ "$APT_GET_UPDATE" = "y" ]]; then
|
||||
_aptUpdate
|
||||
fi
|
||||
|
||||
# Ensure 'dctrl-tools' is installed
|
||||
if [[ "$(dpkg-query --showformat='${Status}\n' --show dctrl-tools \
|
||||
2>/dev/null | awk '{print $3}')" != "installed" ]]; then
|
||||
if [[ "$DOWNLOAD_PACKAGES" = "y" ]]; then
|
||||
_aptInstall dctrl-tools
|
||||
else
|
||||
echo -n "The 'dctrl-tools' package is needed, but DOWNLOAD_PACKAGES is "
|
||||
echo -e "not set to 'y'.\nAborting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Minimum
|
||||
PKG="build-essential cmake git"
|
||||
_mandatory_pkg_alternative libcurl4-openssl-dev libcurl4-gnutls-dev
|
||||
# cmake
|
||||
PKG="$PKG libarchive-dev libbz2-dev libexpat1-dev libjsoncpp-dev liblzma-dev libncurses5-dev procps zlib1g-dev"
|
||||
# TG
|
||||
PKG="$PKG libcgal-dev libgdal-dev libtiff5-dev"
|
||||
# TGGUI/OpenRTI
|
||||
PKG="$PKG libqt4-dev"
|
||||
# SG/FG
|
||||
PKG="$PKG zlib1g-dev freeglut3-dev libboost-dev libopenscenegraph-dev"
|
||||
PKG="$PKG zlib1g-dev freeglut3-dev libboost-dev"
|
||||
_mandatory_pkg_alternative libopenscenegraph-3.4-dev libopenscenegraph-dev \
|
||||
'libopenscenegraph-[0-9]+\.[0-9]+-dev'
|
||||
# FG
|
||||
PKG="$PKG libopenal-dev libudev-dev qt5-default libdbus-1-dev libpng12-dev libplib-dev"
|
||||
PKG="$PKG libopenal-dev libudev-dev qt5-default qtdeclarative5-dev libdbus-1-dev libplib-dev"
|
||||
_mandatory_pkg_alternative libpng-dev libpng12-dev libpng16-dev
|
||||
# The following packages are needed for the built-in launcher
|
||||
_optional_pkg_alternative qml-module-qtquick2
|
||||
_optional_pkg_alternative qml-module-qtquick-window2
|
||||
_optional_pkg_alternative qml-module-qtquick-dialogs
|
||||
# The following packages are only needed for the Qt-based remote Canvas
|
||||
# (comment written at the time of FG 2018.2).
|
||||
_optional_pkg_alternative qtbase5-private-dev
|
||||
_optional_pkg_alternative qtdeclarative5-private-dev
|
||||
# FGPanel
|
||||
PKG="$PKG fluid libbz2-dev libfltk1.3-dev libxi-dev libxmu-dev"
|
||||
# FGAdmin
|
||||
@@ -221,12 +358,8 @@ PKG="$PKG python-tk"
|
||||
# FGx (FGx is not compatible with Qt5, however we have installed Qt5 by default)
|
||||
#PKG="$PKG libqt5xmlpatterns5-dev libqt5webkit5-dev"
|
||||
|
||||
if [ "$DOWNLOAD_PACKAGES" = "y" ]; then
|
||||
echo "Asking password for apt-get operations..."
|
||||
if [ "$APT_GET_UPDATE" = "y" ]; then
|
||||
sudo apt-get update
|
||||
fi
|
||||
sudo apt-get install $PKG
|
||||
if [[ "$DOWNLOAD_PACKAGES" = "y" ]]; then
|
||||
_aptInstall $PKG
|
||||
fi
|
||||
|
||||
#######################################################
|
||||
@@ -265,6 +398,41 @@ if [ -d "$CBD"/fgfs/flightgear ]; then
|
||||
echo "Done"
|
||||
fi
|
||||
|
||||
#######################################################
|
||||
# cmake
|
||||
#######################################################
|
||||
CMAKE_INSTALL_DIR=cmake
|
||||
INSTALL_DIR_CMAKE=$INSTALL_DIR/$CMAKE_INSTALL_DIR
|
||||
cd "$CBD"
|
||||
if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="CMAKE"' ]]; then
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
echo "*************** CMAKE ******************" | tee -a $LOGFILE
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
|
||||
mkdir -p "cmake"
|
||||
cd "$CBD"/cmake
|
||||
_gitDownload https://cmake.org/cmake.git
|
||||
_gitUpdate master
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
cd "$CBD"
|
||||
mkdir -p build/cmake
|
||||
echo "CONFIGURING cmake" >> $LOGFILE
|
||||
cd "$CBD"/build/cmake
|
||||
../../cmake/configure --prefix="$INSTALL_DIR_CMAKE" \
|
||||
2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
|
||||
_make cmake
|
||||
CMAKE="$INSTALL_DIR_CMAKE/bin/cmake"
|
||||
else
|
||||
if [ -x "$INSTALL_DIR_CMAKE/bin/cmake" ]; then
|
||||
CMAKE="$INSTALL_DIR_CMAKE/bin/cmake"
|
||||
else
|
||||
CMAKE=cmake
|
||||
fi
|
||||
fi
|
||||
|
||||
#######################################################
|
||||
# PLIB
|
||||
#######################################################
|
||||
@@ -278,7 +446,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="PLIB"' ]]; then
|
||||
|
||||
mkdir -p "plib"
|
||||
cd "$CBD"/plib
|
||||
_gitDownload git://git.code.sf.net/p/libplib/code
|
||||
_gitDownload https://git.code.sf.net/p/libplib/code
|
||||
_gitUpdate master
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
@@ -286,7 +454,8 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="PLIB"' ]]; then
|
||||
mkdir -p build/plib
|
||||
echo "CONFIGURING plib" >> $LOGFILE
|
||||
cd "$CBD"/build/plib
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_PLIB" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_PLIB" \
|
||||
../../plib 2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
|
||||
@@ -306,7 +475,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="OPENRTI"' ]]; then
|
||||
|
||||
mkdir -p "openrti"
|
||||
cd "$CBD"/openrti
|
||||
_gitDownload git://git.code.sf.net/p/openrti/OpenRTI
|
||||
_gitDownload https://git.code.sf.net/p/openrti/OpenRTI
|
||||
|
||||
if [ "$STABLE" = "STABLE" ]; then
|
||||
_gitUpdate release-0.7
|
||||
@@ -319,7 +488,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="OPENRTI"' ]]; then
|
||||
mkdir -p build/openrti
|
||||
cd "$CBD"/build/openrti
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_OPENRTI" \
|
||||
../../openrti 2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
@@ -335,31 +504,36 @@ INSTALL_DIR_OSG=$INSTALL_DIR/$OSG_INSTALL_DIR
|
||||
cd "$CBD"
|
||||
mkdir -p "openscenegraph"
|
||||
if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="OSG"' ]]; then
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
echo "**************** OSG *******************" | tee -a $LOGFILE
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
cd "$CBD"/openscenegraph
|
||||
_gitDownload http://github.com/openscenegraph/osg.git
|
||||
_gitUpdate OpenSceneGraph-3.2
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
echo "**************** OSG *******************" | tee -a $LOGFILE
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
cd "$CBD"/openscenegraph
|
||||
_gitDownload https://github.com/openscenegraph/osg.git
|
||||
_gitUpdate OpenSceneGraph-3.4
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
cd "$CBD"
|
||||
mkdir -p build/openscenegraph
|
||||
cd "$CBD"/build/openscenegraph
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_OSG" ../../openscenegraph/ 2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
|
||||
_make openscenegraph
|
||||
#FIX FOR 64 BIT COMPILATION
|
||||
if [ -d "$INSTALL_DIR_OSG/lib64" ]; then
|
||||
if [ -L "$INSTALL_DIR_OSG/lib" ]; then
|
||||
echo "link already done"
|
||||
else
|
||||
ln -s "$INSTALL_DIR_OSG/lib64" "$INSTALL_DIR_OSG/lib"
|
||||
fi
|
||||
fi
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
cd "$CBD"
|
||||
mkdir -p build/openscenegraph
|
||||
cd "$CBD"/build/openscenegraph
|
||||
rm -f CMakeCache.txt
|
||||
if [ "$BUILD_TYPE" = "Debug" ]; then
|
||||
OSG_BUILD_TYPE=Debug
|
||||
else
|
||||
OSG_BUILD_TYPE=Release
|
||||
fi
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$OSG_BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_OSG" ../../openscenegraph/ 2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
|
||||
_make openscenegraph
|
||||
#FIX FOR 64 BIT COMPILATION
|
||||
if [ -d "$INSTALL_DIR_OSG/lib64" ]; then
|
||||
if [ -L "$INSTALL_DIR_OSG/lib" ]; then
|
||||
echo "link already done"
|
||||
else
|
||||
ln -s "$INSTALL_DIR_OSG/lib64" "$INSTALL_DIR_OSG/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#######################################################
|
||||
@@ -375,7 +549,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="SIMGEAR"' ]]; then
|
||||
|
||||
mkdir -p "simgear"
|
||||
cd "$CBD"/simgear
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/simgear
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/simgear
|
||||
_gitUpdate $FGVERSION
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
@@ -383,7 +557,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="SIMGEAR"' ]]; then
|
||||
mkdir -p build/simgear
|
||||
cd "$CBD"/build/simgear
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_SIMGEAR" \
|
||||
-DCMAKE_PREFIX_PATH="$INSTALL_DIR_OSG;$INSTALL_DIR_OPENRTI" \
|
||||
$SG_CMAKEARGS \
|
||||
@@ -408,7 +582,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGFS"' || "$(declare -p WHAT
|
||||
cd "$CBD"/flightgear
|
||||
|
||||
if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGFS"' ]]; then
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/flightgear
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/flightgear
|
||||
_gitUpdate $FGVERSION
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
@@ -416,7 +590,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGFS"' || "$(declare -p WHAT
|
||||
mkdir -p build/flightgear
|
||||
cd "$CBD"/build/flightgear
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DENABLE_FLITE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_FGFS" \
|
||||
-DCMAKE_PREFIX_PATH="$INSTALL_DIR_SIMGEAR;$INSTALL_DIR_OSG;$INSTALL_DIR_OPENRTI;$INSTALL_DIR_PLIB" \
|
||||
@@ -435,7 +609,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGFS"' || "$(declare -p WHAT
|
||||
echo "**************** DATA ******************" | tee -a $LOGFILE
|
||||
echo "****************************************" | tee -a $LOGFILE
|
||||
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/fgdata
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/fgdata
|
||||
_gitUpdate $FGVERSION
|
||||
fi
|
||||
cd "$CBD"
|
||||
@@ -453,7 +627,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGFS"' || "$(declare -p WHAT
|
||||
echo "cd \$(dirname \$0)" >> $SCRIPT
|
||||
echo "cd $SUB_INSTALL_DIR/$FGFS_INSTALL_DIR/bin" >> $SCRIPT
|
||||
echo "export LD_LIBRARY_PATH=../../$SIMGEAR_INSTALL_DIR/lib:../../$OSG_INSTALL_DIR/lib:../../$OPENRTI_INSTALL_DIR/lib:../../$PLIB_INSTALL_DIR/lib" >> $SCRIPT
|
||||
echo "gdb --directory="\$P1"/fgfs/source/src/ --args fgfs --fg-root=\$PWD/../fgdata/ \$@" >> $SCRIPT
|
||||
echo "gdb --directory=$CBD/flightgear/src --args fgfs --fg-root=\$PWD/../fgdata/ \$@" >> $SCRIPT
|
||||
chmod 755 $SCRIPT
|
||||
|
||||
SCRIPT=run_fgcom.sh
|
||||
@@ -477,7 +651,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGRUN"' ]]; then
|
||||
|
||||
mkdir -p "fgrun"
|
||||
cd "$CBD"/fgrun
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/fgrun
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/fgrun
|
||||
_gitUpdate $FGVERSION
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
@@ -485,7 +659,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGRUN"' ]]; then
|
||||
mkdir -p build/fgrun
|
||||
cd "$CBD"/build/fgrun
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_FGRUN" \
|
||||
-DCMAKE_PREFIX_PATH="$INSTALL_DIR_SIMGEAR" \
|
||||
../../fgrun/ 2>&1 | tee -a $LOGFILE
|
||||
@@ -499,7 +673,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="FGRUN"' ]]; then
|
||||
echo "#!/bin/sh" > $SCRIPT
|
||||
echo "cd \$(dirname \$0)" >> $SCRIPT
|
||||
echo "cd $SUB_INSTALL_DIR/$FGRUN_INSTALL_DIR/bin" >> $SCRIPT
|
||||
echo "export LD_LIBRARY_PATH=$INSTALL_DIR_SIMGEAR/lib" >> $SCRIPT
|
||||
echo "export LD_LIBRARY_PATH=../../$SIMGEAR_INSTALL_DIR/lib:../../$OSG_INSTALL_DIR/lib:../../$OPENRTI_INSTALL_DIR/lib:../../$PLIB_INSTALL_DIR/lib" >> $SCRIPT
|
||||
echo "./fgrun --fg-exe=\$PWD/../../$FGFS_INSTALL_DIR/bin/fgfs --fg-root=\$PWD/../../$FGFS_INSTALL_DIR/fgdata \$@" >> $SCRIPT
|
||||
chmod 755 $SCRIPT
|
||||
fi
|
||||
@@ -605,7 +779,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="ATCPIE"' ]]; then
|
||||
|
||||
mkdir -p "$INSTALL_DIR_ATCPIE"
|
||||
cd $INSTALL_DIR_ATCPIE
|
||||
_gitDownload git://git.code.sf.net/p/atc-pie/code
|
||||
_gitDownload https://git.code.sf.net/p/atc-pie/code
|
||||
_gitUpdate master
|
||||
|
||||
cd "$CBD"
|
||||
@@ -658,7 +832,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="TERRAGEAR"' ]]; then
|
||||
|
||||
mkdir -p "terragear"
|
||||
cd "$CBD"/terragear
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/terragear
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/terragear
|
||||
_gitUpdate scenery/ws2.0
|
||||
|
||||
if [ "$RECONFIGURE" = "y" ]; then
|
||||
@@ -666,7 +840,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="TERRAGEAR"' ]]; then
|
||||
mkdir -p build/terragear
|
||||
cd "$CBD"/build/terragear
|
||||
rm -f CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Debug" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="Debug" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="$INSTALL_DIR_TG" \
|
||||
-DCMAKE_PREFIX_PATH="$INSTALL_DIR_SIMGEAR;$INSTALL_DIR_CGAL" \
|
||||
../../terragear/ 2>&1 | tee -a $LOGFILE
|
||||
@@ -709,7 +883,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="TERRAGEARGUI"' ]]; then
|
||||
|
||||
mkdir -p "terrageargui"
|
||||
cd "$CBD"/terrageargui
|
||||
_gitDownload git://git.code.sf.net/p/flightgear/fgscenery/terrageargui
|
||||
_gitDownload https://git.code.sf.net/p/flightgear/fgscenery/terrageargui
|
||||
_gitUpdate master
|
||||
|
||||
|
||||
@@ -718,7 +892,7 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="TERRAGEARGUI"' ]]; then
|
||||
mkdir -p build/terrageargui
|
||||
cd "$CBD"/build/terrageargui
|
||||
rm -f ../../terrageargui/CMakeCache.txt
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" \
|
||||
"$CMAKE" -DCMAKE_BUILD_TYPE="Release" \
|
||||
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR_TGGUI" \
|
||||
../../terrageargui 2>&1 | tee -a $LOGFILE
|
||||
fi
|
||||
@@ -743,6 +917,24 @@ if [[ "$(declare -p WHATTOBUILD)" =~ '['([0-9]+)']="TERRAGEARGUI"' ]]; then
|
||||
echo "./TerraGUI \$@" >> run_terrageargui.sh
|
||||
fi
|
||||
|
||||
# Print optional package alternatives that didn't match (this helps with
|
||||
# troubleshooting)
|
||||
if [[ ${#UNMATCHED_OPTIONAL_PKG_ALTERNATIVES[@]} -gt 0 ]]; then
|
||||
echo | tee -a "$LOGFILE"
|
||||
printf "The following optional package alternative(s) didn't match:\n\n" \
|
||||
| tee -a "$LOGFILE"
|
||||
|
||||
for alt in "${UNMATCHED_OPTIONAL_PKG_ALTERNATIVES[@]}"; do
|
||||
printf " %s\n" "$alt" | tee -a "$LOGFILE"
|
||||
done
|
||||
|
||||
printf "\nThis could explain missing optional features in FlightGear or \
|
||||
other software\ninstalled by $PROGNAME.\n" | tee -a "$LOGFILE"
|
||||
else
|
||||
printf "All optional package alternatives have found a matching package.\n" \
|
||||
| tee -a "$LOGFILE"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "download_and_compile.sh has finished to work"
|
||||
|
||||
|
||||
2
fgdata
2
fgdata
Submodule fgdata updated: a6d7af5db6...aabe57f1fc
@@ -476,8 +476,8 @@ Nasal (Canvas map) probably wouldn't break anything, but guessing it's a bad ide
|
||||
base_texture_files=[]
|
||||
for t in find_unused_textures(input_path,return_used_noregions=True):
|
||||
base_texture_files.extend([path_join("Textures",t),path_join("Textures.high",t)])
|
||||
#no longer a significant problem with exclude_dirs: if os.path.exists(path_join(input_path,".git")):
|
||||
#print(input_path,"appears to be a git clone; this will work, but the result will be larger than starting from a standard flightgear-data package.\nTo create this use (adjusting paths as necessary) rsync -av --filter=\"merge /home/rnpalmer/fs_dev/git/fgmeta/base-package.rules\" ~/fs_dev/git/fgdata ~/fs_dev/flightgear/data_full")
|
||||
#no longer a significant problem with exclude_dirs, and no longer exists for new fgdata: if os.path.exists(path_join(input_path,".git")):
|
||||
#print(input_path,"""appears to be a git clone; this will work, but the result will be larger than starting from a standard flightgear-data package.\nTo create this use (adjusting paths as necessary) rsync -av --filter="merge /home/rnpalmer/FlightGear/source/fgmeta/base-package.rules" ~/FlightGear/source/fgdata ~/FlightGear/data_full""")
|
||||
if os.path.exists(output_path.format("base")) and os.listdir(output_path.format("base")):
|
||||
print("output path",output_path,"non-empty, aborting to avoid data loss\nIf you did want to lose its previous contents, run:\nrm -r",output_path,"\nthen re-run this script")
|
||||
return
|
||||
|
||||
2
fgrun
2
fgrun
Submodule fgrun updated: e6aa576402...3fb3be1935
Submodule flightgear updated: c2e3f4796c...3798f8e182
1
getstart
Submodule
1
getstart
Submodule
Submodule getstart added at b8753789a8
@@ -1,50 +0,0 @@
|
||||
# git diff --quiet e5f841bc84d31fee339191a59b8746cb4eb8074c -- ./Aircraft/
|
||||
|
||||
import subprocess
|
||||
import os, sgprops
|
||||
|
||||
class GITCatalogRepository:
|
||||
def __init__(self, node, singleAircraft = False):
|
||||
self._path = node.getValue("path")
|
||||
|
||||
if not os.path.exists(os.path.join(self._path , ".git")):
|
||||
raise RuntimeError("not a Git directory:" + self._path )
|
||||
|
||||
self._usesSubmodules = node.getValue("uses-submodules", False)
|
||||
self._singleAircraft = singleAircraft
|
||||
|
||||
self._currentRevision = subprocess.check_output(["git", "rev-parse", "HEAD"],
|
||||
cwd = self._path)
|
||||
|
||||
self._aircraftPath = None
|
||||
if node.hasChild("scan-suffix"):
|
||||
self._aircraftPath = os.path.join(path, node.getValue("scan-suffix"))
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def aircraftPath(self):
|
||||
return self._aircraftPath
|
||||
|
||||
def hasPathChanged(self, path, oldRev):
|
||||
diffArgs = ["git", "diff", "--quiet", oldRev, "--"]
|
||||
if not (self._usesSubmodules and self._singleAircraft):
|
||||
diffArgs.append(path)
|
||||
|
||||
return subprocess.call(diffArgs, cwd = self._path)
|
||||
|
||||
def update(self):
|
||||
subprocess.call(["git", "pull"])
|
||||
self._currentRevision = subprocess.check_output(["git", "rev-parse", "HEAD"],
|
||||
cwd = self._path)
|
||||
|
||||
if self._usesSubmodules:
|
||||
subprocess.call(["git", "submodule", "update"], cwd = self._path)
|
||||
|
||||
def scmRevisionForPath(self, path):
|
||||
if self._usesSubmodules:
|
||||
return subprocess.check_output(["git", "rev-parse", "HEAD"], cwd = self._path)
|
||||
|
||||
return self._currentRevision
|
||||
@@ -1,34 +0,0 @@
|
||||
# git diff --quiet e5f841bc84d31fee339191a59b8746cb4eb8074c -- ./Aircraft/
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sgprops
|
||||
|
||||
import git_catalog_repository
|
||||
|
||||
class GitDiscreteSCM:
|
||||
def __init__(self, node):
|
||||
|
||||
configNode = node.parent
|
||||
|
||||
self._repos = {}
|
||||
|
||||
# iterate over aicraft paths finding repositories
|
||||
for g in config.getChildren("aircraft-dir"):
|
||||
repo = GITCatalogRepository(g, useSubmodules = False,
|
||||
singleAircraft = True)
|
||||
|
||||
|
||||
def hasPathChanged(self, path, oldRev):
|
||||
|
||||
return self._repos[path].hasPathChanged(path, oldRev)
|
||||
|
||||
def update(self):
|
||||
for r in self._repos:
|
||||
r.update()
|
||||
|
||||
def scmRevisionForPath(self, path):
|
||||
return self._repos[path].scmRevisionForPath(path)
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ echo "Build path is: $PATH"
|
||||
###############################################################################
|
||||
echo "Starting on SimGear"
|
||||
pushd sgBuild
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DENABLE_CURL:BOOL="ON" -DCMAKE_BUILD_TYPE=RelWithDebInfo ../simgear
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DCMAKE_BUILD_TYPE=RelWithDebInfo ../simgear
|
||||
|
||||
# compile
|
||||
make
|
||||
@@ -39,7 +39,14 @@ popd
|
||||
################################################################################
|
||||
echo "Starting on FlightGear"
|
||||
pushd fgBuild
|
||||
cmake -DFG_NIGHTLY=1 -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DCMAKE_BUILD_TYPE=RelWithDebInfo ../flightgear
|
||||
|
||||
if [ $FG_IS_RELEASE == '1' ]; then
|
||||
FGBUILDTYPE=Release
|
||||
else
|
||||
FGBUILDTYPE=Nightly
|
||||
fi
|
||||
|
||||
cmake -DFG_BUILD_TYPE=$FGBUILDTYPE -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DCMAKE_BUILD_TYPE=RelWithDebInfo ../flightgear
|
||||
|
||||
make
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ puts "Is-release? : ##{$isRelease}"
|
||||
$prefixDir=Dir.pwd + "/dist"
|
||||
dmgDir=Dir.pwd + "/image"
|
||||
srcDir=Dir.pwd + "/flightgear"
|
||||
qmlDir=srcDir + "/src/GUI/qml"
|
||||
|
||||
puts "Erasing previous image dir"
|
||||
`rm -rf #{dmgDir}`
|
||||
@@ -48,8 +49,10 @@ bundle=dmgDir + "/FlightGear.app"
|
||||
|
||||
# run macdeployt before we rename the bundle, otherwise it
|
||||
# can't find the bundle executable
|
||||
# also note if adding options here, the bundle path has to be
|
||||
# the first argument to macdeployqt
|
||||
puts "Running macdeployqt on the bundle to copy Qt libraries"
|
||||
`macdeployqt #{$prefixDir}/fgfs.app`
|
||||
`macdeployqt #{$prefixDir}/fgfs.app -qmldir=#{qmlDir}`
|
||||
|
||||
puts "Moving & renaming app bundle"
|
||||
`mkdir -p #{dmgDir}`
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os, sys, re, glob, shutil
|
||||
import subprocess
|
||||
import sgprops
|
||||
import argparse
|
||||
import urllib2
|
||||
import package as pkg
|
||||
|
||||
import svn_catalog_repository
|
||||
import git_catalog_repository
|
||||
import git_discrete_repository
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--clean", help="Regenerate every package",
|
||||
action="store_true")
|
||||
parser.add_argument("--update", help="Update/pull SCM source",
|
||||
action="store_true")
|
||||
parser.add_argument("--force-dirty", dest="forcedirty",
|
||||
help="Mark every package as dirty", action="store_true")
|
||||
parser.add_argument("--no-update",
|
||||
dest = "noupdate",
|
||||
help="Disable updating from SCM source",
|
||||
action="store_true")
|
||||
parser.add_argument("--no-upload",
|
||||
dest = "noupload",
|
||||
help="Disable uploading to destination server",
|
||||
action="store_true")
|
||||
parser.add_argument("dir", help="Catalog directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
CATALOG_VERSION = 4
|
||||
includePaths = []
|
||||
packages = {}
|
||||
|
||||
def scanPackages(scmRepo):
|
||||
result = []
|
||||
globPath = scmRepo.aircraftPath
|
||||
if globPath is None:
|
||||
return result
|
||||
|
||||
print "Scanning", globPath
|
||||
print os.getcwd()
|
||||
for d in glob.glob(globPath):
|
||||
# check dir contains at least one -set.xml file
|
||||
if len(glob.glob(os.path.join(d, "*-set.xml"))) == 0:
|
||||
print "no -set.xml in", d
|
||||
continue
|
||||
|
||||
result.append(pkg.PackageData(d, scmRepo))
|
||||
|
||||
return result
|
||||
|
||||
def initScmRepository(node):
|
||||
scmType = node.getValue("type")
|
||||
if (scmType == "svn"):
|
||||
return svn_catalog_repository.SVNCatalogRepository(node)
|
||||
elif (scmType == "git"):
|
||||
return git_catalog_repository.GITCatalogRepository(node)
|
||||
elif (scmType == "git-discrete"):
|
||||
return git_discrete_repository.GitDiscreteSCM(node)
|
||||
elif (scmType == None):
|
||||
raise RuntimeError("No scm/type defined in catalog configuration")
|
||||
else:
|
||||
raise RuntimeError("Unspported SCM type:" + scmType)
|
||||
|
||||
def initRepositories():
|
||||
repositories = []
|
||||
|
||||
for scm in config.getChildren("scm"):
|
||||
scmRepo = initScmRepository(scm)
|
||||
if args.update or (not args.noupdate and scm.getValue("update")):
|
||||
scmRepo.update()
|
||||
# presumably include repos in parse path
|
||||
# TODO: make this configurable
|
||||
includePaths.append(scmRepo.path)
|
||||
repositories.append(scmRepo)
|
||||
|
||||
return repositories
|
||||
|
||||
def processUpload(node, outputPath):
|
||||
if args.noupload or not node.getValue("enabled", True):
|
||||
print "Upload disabled"
|
||||
return
|
||||
|
||||
uploadType = node.getValue("type")
|
||||
if (uploadType == "rsync"):
|
||||
subprocess.call(["rsync", node.getValue("args", "-az"), ".",
|
||||
node.getValue("remote")],
|
||||
cwd = outputPath)
|
||||
elif (uploadType == "rsync-ssh"):
|
||||
print "Doing rsync upload to:", node.getValue("remote")
|
||||
subprocess.call(["rsync", node.getValue("args", "-azve"),
|
||||
"ssh", ".",
|
||||
node.getValue("remote")],
|
||||
cwd = outputPath)
|
||||
elif (uploadType == "scp"):
|
||||
subprocess.call(["scp", node.getValue("args", "-r"), ".",
|
||||
node.getValue("remote")],
|
||||
cwd = outputPath)
|
||||
else:
|
||||
raise RuntimeError("Unsupported upload type:" + uploadType)
|
||||
|
||||
def parseExistingCatalog():
|
||||
global existingCatalogPath
|
||||
global previousCatalog
|
||||
|
||||
# contains existing catalog
|
||||
existingCatalogPath = os.path.join(outPath, 'catalog.xml')
|
||||
|
||||
if not os.path.exists(existingCatalogPath):
|
||||
url = config.getValue("template/url")
|
||||
print "Attempting downloading from", url
|
||||
try:
|
||||
# can happen on new or from clean, try to pull current
|
||||
# catalog from the upload location
|
||||
response = urllib2.urlopen(url, timeout = 5)
|
||||
content = response.read()
|
||||
f = open(existingCatalogPath, 'w' )
|
||||
f.write( content )
|
||||
f.close()
|
||||
print "...worked"
|
||||
except urllib2.URLError as e:
|
||||
print "Downloading current catalog failed", e, "from", url
|
||||
|
||||
rootDir = args.dir
|
||||
if not os.path.isabs(rootDir):
|
||||
rootDir = os.path.abspath(rootDir)
|
||||
os.chdir(rootDir)
|
||||
|
||||
configPath = 'catalog.config.xml'
|
||||
if not os.path.exists(configPath):
|
||||
raise RuntimeError("no config file found at:" + configPath)
|
||||
|
||||
config = sgprops.readProps(configPath)
|
||||
|
||||
# out path
|
||||
outPath = config.getValue('output-dir')
|
||||
if outPath is None:
|
||||
# default out path
|
||||
outPath = os.path.join(rootDir, "output")
|
||||
elif not os.path.isabs(outPath):
|
||||
outPath = os.path.join(rootDir, "output")
|
||||
|
||||
if args.clean:
|
||||
print "Cleaning output"
|
||||
shutil.rmtree(outPath)
|
||||
|
||||
if not os.path.exists(outPath):
|
||||
os.mkdir(outPath)
|
||||
|
||||
thumbnailPath = os.path.join(outPath, config.getValue('thumbnail-dir', "thumbnails"))
|
||||
if not os.path.exists(thumbnailPath):
|
||||
os.mkdir(thumbnailPath)
|
||||
|
||||
thumbnailUrls = list(t.value for t in config.getChildren("thumbnail-url"))
|
||||
|
||||
for i in config.getChildren("include-dir"):
|
||||
if not os.path.exists(i.value):
|
||||
print "Skipping missing include path:", i.value
|
||||
continue
|
||||
includePaths.append(i.value)
|
||||
|
||||
parseExistingCatalog()
|
||||
repositories = initRepositories()
|
||||
|
||||
for scm in repositories:
|
||||
for p in scanPackages(scm):
|
||||
try:
|
||||
p.scanSetXmlFiles(includePaths)
|
||||
packages[p.id] = p
|
||||
except:
|
||||
print "Skipping SCM package due to exception:", p.path
|
||||
|
||||
if os.path.exists(existingCatalogPath):
|
||||
try:
|
||||
previousCatalog = sgprops.readProps(existingCatalogPath)
|
||||
except:
|
||||
print "Previous catalog is malformed"
|
||||
previousCatalog = sgprops.Node()
|
||||
|
||||
for p in previousCatalog.getChildren("package"):
|
||||
pkgId = p.getValue("id")
|
||||
if not pkgId in packages.keys():
|
||||
print "Orphaned old package:", pkgId
|
||||
continue
|
||||
|
||||
packages[pkgId].setPreviousData(p)
|
||||
else:
|
||||
print "No previous catalog"
|
||||
|
||||
catalogNode = sgprops.Node("catalog")
|
||||
sgprops.copy(config.getChild("template"), catalogNode)
|
||||
|
||||
catalogNode.getChild("catalog-version", create = True).value = CATALOG_VERSION
|
||||
mirrorUrls = list(m.value for m in config.getChildren("mirror"))
|
||||
|
||||
packagesToGenerate = []
|
||||
for p in packages.values():
|
||||
if p.isSourceModified or args.forcedirty:
|
||||
packagesToGenerate.append(p)
|
||||
else:
|
||||
p.useExistingCatalogData()
|
||||
|
||||
excludeFilePath = os.path.join(rootDir, "zip-excludes.lst")
|
||||
|
||||
# def f(x):
|
||||
# x.generateZip(outPath)
|
||||
# x.extractThumbnails(thumbnailPath)
|
||||
# return True
|
||||
#
|
||||
# p = Pool(8)
|
||||
# print(p.map(f,packagesToGenerate))
|
||||
|
||||
for p in packagesToGenerate:
|
||||
p.generateZip(outPath, excludeFilePath)
|
||||
p.extractThumbnails(thumbnailPath)
|
||||
|
||||
print "Creating catalog"
|
||||
for p in packages.values():
|
||||
catalogNode.addChild(p.packageNode(mirrorUrls, thumbnailUrls[0]))
|
||||
|
||||
catalogNode.write(os.path.join(outPath, "catalog.xml"))
|
||||
|
||||
for up in config.getChildren("upload"):
|
||||
processUpload(up, outPath)
|
||||
239
package.py
239
package.py
@@ -1,239 +0,0 @@
|
||||
import os, subprocess
|
||||
import sgprops
|
||||
import hashlib # for MD5
|
||||
import shutil # for copy2
|
||||
import catalogTags
|
||||
|
||||
standardTagSet = frozenset(catalogTags.tags)
|
||||
def isNonstandardTag(t):
|
||||
return t not in standardTagSet
|
||||
|
||||
thumbnailNames = ["thumbnail.png", "thumbnail.jpg"]
|
||||
|
||||
class VariantData:
|
||||
def __init__(self, path, node):
|
||||
#self._primary = primary
|
||||
self._path = path
|
||||
self._name = node.getValue("sim/description")
|
||||
if (not self._name):
|
||||
print "Missing description for " + path
|
||||
self._name = "Missing description:" + self.id
|
||||
|
||||
# ratings
|
||||
|
||||
# seperate thumbnails
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._path[:-8] # "remove -set.xml" (8 chars)
|
||||
|
||||
@property
|
||||
def catalogNode(self):
|
||||
n = sgprops.Node("variant")
|
||||
n.addChild("id").value = self.id
|
||||
n.addChild("name").value = self.name
|
||||
return n
|
||||
|
||||
class PackageData:
|
||||
def __init__(self, path, scmRepo):
|
||||
self._path = path
|
||||
self._scm = scmRepo
|
||||
self._previousSCMRevision = None
|
||||
self._previousRevision = 0
|
||||
self._thumbnails = []
|
||||
self._variants = {}
|
||||
self._revision = 0
|
||||
self._md5 = None
|
||||
self._fileSize = 0
|
||||
self._primarySetXmlPath = None
|
||||
self._node = sgprops.Node("package")
|
||||
|
||||
def setPreviousData(self, node):
|
||||
self._previousRevision = node.getValue("revision")
|
||||
self._previousMD5 = node.getValue("md5")
|
||||
self._previousSCMRevision = node.getValue("scm-revision")
|
||||
self._fileSize = int(node.getValue("file-size-bytes"))
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._primarySetXmlPath
|
||||
|
||||
@property
|
||||
def thumbnails(self):
|
||||
return self._thumbnails
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def variants(self):
|
||||
return self._variants
|
||||
|
||||
@property
|
||||
def scmRevision(self):
|
||||
currentRev = self._scm.scmRevisionForPath(self.path)
|
||||
if (currentRev is None):
|
||||
raise RuntimeError("Unable to query SCM revision of files")
|
||||
|
||||
return currentRev
|
||||
|
||||
@property
|
||||
def isSourceModified(self):
|
||||
if (self._previousSCMRevision == None):
|
||||
return True
|
||||
|
||||
if (self._previousSCMRevision == self.scmRevision):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def scanSetXmlFiles(self, includes):
|
||||
foundPrimary = False
|
||||
foundMultiple = False
|
||||
|
||||
for f in os.listdir(self.path):
|
||||
if not f.endswith("-set.xml"):
|
||||
continue
|
||||
|
||||
p = os.path.join(self.path, f)
|
||||
node = sgprops.readProps(p, includePaths = includes)
|
||||
if not node.hasChild("sim"):
|
||||
continue
|
||||
|
||||
simNode = node.getChild("sim")
|
||||
# honour variosu exclusion flags
|
||||
if (simNode.getValue("exclude-from-catalog", False) or simNode.getValue("exclude-from-gui", False)):
|
||||
continue
|
||||
|
||||
primary = simNode.getValue("variant-of", None)
|
||||
if primary:
|
||||
if not primary in self.variants:
|
||||
self._variants[primary] = []
|
||||
self._variants[primary].append(VariantData(f, node))
|
||||
continue
|
||||
|
||||
if foundPrimary:
|
||||
if not foundMultiple:
|
||||
print "Multiple primary -set.xml files at:" + self.path
|
||||
print "\t" + p
|
||||
foundMultiple = True
|
||||
continue
|
||||
else:
|
||||
foundPrimary = True;
|
||||
self._primarySetXmlPath = f[:-8] # trim -set.xml
|
||||
|
||||
self.parsePrimarySetNode(simNode)
|
||||
|
||||
for n in thumbnailNames:
|
||||
if os.path.exists(os.path.join(self.path, n)):
|
||||
self._thumbnails.append(n)
|
||||
|
||||
if not foundPrimary:
|
||||
raise RuntimeError("No primary -set.xml found at:" + self.path)
|
||||
|
||||
|
||||
|
||||
def parsePrimarySetNode(self, sim):
|
||||
|
||||
# basic / mandatory values
|
||||
self._node.addChild('name').value = sim.getValue('description')
|
||||
|
||||
longDesc = sim.getValue('long-description')
|
||||
if longDesc is not None:
|
||||
self._node.addChild('description').value = longDesc
|
||||
|
||||
# copy all the standard values
|
||||
for p in ['status', 'author', 'license']:
|
||||
v = sim.getValue(p)
|
||||
if v is not None:
|
||||
self._node.addChild(p).value = v
|
||||
|
||||
# ratings
|
||||
if sim.hasChild('rating'):
|
||||
pkgRatings = self._node.addChild('rating')
|
||||
for r in ['FDM', 'systems', 'cockpit', 'model']:
|
||||
pkgRatings.addChild(r).value = sim.getValue('rating/' + r, 0)
|
||||
|
||||
# copy tags
|
||||
if sim.hasChild('tags'):
|
||||
for c in sim.getChild('tags').getChildren('tag'):
|
||||
if isNonstandardTag(c.value):
|
||||
print "Skipping non-standard tag:", c.value, self.path
|
||||
else:
|
||||
self._node.addChild('tag').value = c.value
|
||||
|
||||
for t in sim.getChildren("thumbnail"):
|
||||
self._thumbnails.append(t.value)
|
||||
|
||||
def validate(self):
|
||||
for t in self._thumbnails:
|
||||
if not os.path.exists(os.path.join(self.path, t)):
|
||||
raise RuntimeError("missing thumbnail:" + t);
|
||||
|
||||
def generateZip(self, outDir, globalExcludePath):
|
||||
self._revision = self._previousRevision + 1
|
||||
|
||||
baseName = os.path.basename(self.path)
|
||||
zipName = baseName + ".zip"
|
||||
zipFilePath = os.path.join(outDir, zipName)
|
||||
|
||||
os.chdir(os.path.dirname(self.path))
|
||||
|
||||
print "Creating zip", zipFilePath
|
||||
# anything we can do to make this faster?
|
||||
|
||||
zipArgs = ['zip', '--quiet', '-r']
|
||||
if os.path.exists(globalExcludePath):
|
||||
zipArgs += [ "-x@" + globalExcludePath]
|
||||
|
||||
excludePath = os.path.join(self.path, 'package-exclude.lst')
|
||||
if (os.path.exists(excludePath)):
|
||||
print self.id, "has zip exclude list"
|
||||
zipArgs += ["-x@" + excludePath]
|
||||
|
||||
zipArgs += [zipFilePath, baseName]
|
||||
subprocess.call(zipArgs)
|
||||
|
||||
zipFile = open(zipFilePath, 'r')
|
||||
self._md5 = hashlib.md5(zipFile.read()).hexdigest()
|
||||
self._fileSize = os.path.getsize(zipFilePath)
|
||||
|
||||
def useExistingCatalogData(self):
|
||||
self._md5 = self._previousMD5
|
||||
|
||||
def packageNode(self, mirrorUrls, thumbnailUrl):
|
||||
self._node.addChild("id").value = self.id
|
||||
self._node.getChild("md5", create = True).value = self._md5
|
||||
self._node.getChild("file-size-bytes", create = True).value = self._fileSize
|
||||
self._node.getChild("revision", create = True).value = int(self._revision)
|
||||
self._node.getChild("scm-revision", create = True).value = self.scmRevision
|
||||
|
||||
baseName = os.path.basename(self.path)
|
||||
self._node.getChild("dir", create = True).value = baseName
|
||||
zipName = baseName + ".zip"
|
||||
|
||||
for m in mirrorUrls:
|
||||
self._node.addChild("url").value = m + "/" + zipName
|
||||
|
||||
for t in self._thumbnails:
|
||||
self._node.addChild("thumbnail-path").value = t
|
||||
self._node.addChild("thumbnail").value = thumbnailUrl + "/" + self.id + "_" + t
|
||||
|
||||
for pr in self._variants:
|
||||
for vr in self._variants[pr]:
|
||||
self._node.addChild(vr.catalogNode)
|
||||
|
||||
return self._node
|
||||
|
||||
def extractThumbnails(self, thumbnailDir):
|
||||
for t in self._thumbnails:
|
||||
fullName = self.id + "_" + t
|
||||
shutil.copy2(os.path.join(self._path, t),
|
||||
os.path.join(thumbnailDir, fullName)
|
||||
)
|
||||
# TODO : verify image format, size and so on
|
||||
@@ -8,14 +8,19 @@ import os, sys, re, fnmatch
|
||||
from subprocess import call
|
||||
|
||||
suffix = '.dmg'
|
||||
release_version = "unknown"
|
||||
|
||||
if sys.argv[1] == 'windows':
|
||||
suffix = '.exe'
|
||||
if sys.argv[1] == 'linux':
|
||||
suffix = '.tar.bz2'
|
||||
|
||||
isReleaseCandidate = False
|
||||
isRelease = False
|
||||
if len(sys.argv) > 2 and sys.argv[2] == 'release':
|
||||
isReleaseCandidate = True
|
||||
isRelease = True
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
release_version = sys.argv[3]
|
||||
|
||||
allSuffix = '*' + suffix
|
||||
|
||||
@@ -25,10 +30,10 @@ sourceForgeUserHost = "jmturner@frs.sourceforge.net"
|
||||
sftpCommandFile = "sftp-commands"
|
||||
symbolDir = "/home/jenkins/symbols"
|
||||
|
||||
if isReleaseCandidate:
|
||||
if isRelease:
|
||||
publicRoot = "/var/www/html/builds/rc"
|
||||
incomingDir = "/home/jenkins/incoming"
|
||||
sourceForgePath = "/home/frs/project/f/fl/flightgear/release-candidate/"
|
||||
sourceForgePath = "/home/frs/project/f/fl/flightgear/release-" + release_version + "/"
|
||||
else:
|
||||
publicRoot = "/var/www/html/builds/nightly"
|
||||
incomingDir = "/home/jenkins/nightly-incoming"
|
||||
@@ -81,15 +86,15 @@ for file in incomingFiles:
|
||||
|
||||
outFile = file
|
||||
# insert -rc before suffix
|
||||
if isReleaseCandidate:
|
||||
m = re.match(r'(\w+-\d+\.\d+\.\d+[\w-]*)' + suffix, file)
|
||||
outFile = m.group(1) + '-rc' + suffix
|
||||
print "RC out name is " + outFile
|
||||
#if isRelease:
|
||||
#m = re.match(r'(\w+-\d+\.\d+\.\d+[\w-]*)' + suffix, file)
|
||||
#outFile = m.group(1) + '-rc' + suffix
|
||||
#print "RC out name is " + outFile
|
||||
|
||||
os.rename(srcFile, outFile)
|
||||
newFiles.append(outFile)
|
||||
|
||||
if not isReleaseCandidate:
|
||||
if not isRelease:
|
||||
# symlink for stable web URL
|
||||
m = re.match(r'(\w+)-\d+\.\d+\.\d+-([\w-]+)' + suffix, file)
|
||||
latestName = m.group(1) + '-latest-' + m.group(2) + suffix
|
||||
@@ -102,17 +107,17 @@ for file in incomingFiles:
|
||||
|
||||
|
||||
# remove files from SF
|
||||
if len(oldFiles) > 0:
|
||||
f = open(sftpCommandFile, 'w')
|
||||
f.write("cd " + sourceForgePath + '\n')
|
||||
for file in oldFiles:
|
||||
print "Removing file " + file + " from SourceForge"
|
||||
f.write("rm " + file + '\n')
|
||||
f.write("bye\n")
|
||||
f.close()
|
||||
|
||||
call(["sftp", "-b", sftpCommandFile, sourceForgeUserHost])
|
||||
os.remove(sftpCommandFile)
|
||||
#if len(oldFiles) > 0:
|
||||
# f = open(sftpCommandFile, 'w')
|
||||
# f.write("cd " + sourceForgePath + '\n')
|
||||
# for file in oldFiles:
|
||||
# print "Removing file " + file + " from SourceForge"
|
||||
# f.write("rm " + file + '\n')
|
||||
# f.write("bye\n")
|
||||
# f.close()
|
||||
#
|
||||
# call(["sftp", "-b", sftpCommandFile, sourceForgeUserHost])
|
||||
# os.remove(sftpCommandFile)
|
||||
|
||||
# upload to SourceForge
|
||||
for file in newFiles:
|
||||
|
||||
126
python3-flightgear/README-l10n.txt
Normal file
126
python3-flightgear/README-l10n.txt
Normal file
@@ -0,0 +1,126 @@
|
||||
-*- coding: utf-8 -*-
|
||||
|
||||
Quick start for the localization (l10n) scripts
|
||||
===============================================
|
||||
|
||||
The following assumes that all of these are in present in
|
||||
$FG_ROOT/Translations:
|
||||
- the default translation (default/*.xml);
|
||||
- the legacy FlightGear XML localization files (<language_code>/*.xml);
|
||||
- except for 'fg-convert-translation-files' which creates them, existing
|
||||
XLIFF 1.2 files (<language_code>/FlightGear-nonQt.xlf).
|
||||
|
||||
Note: the legacy FlightGear XML localization files are only needed by
|
||||
'fg-convert-translation-files' when migrating to the XLIFF format. The
|
||||
other scripts only need the default translation and obviously, for
|
||||
'fg-update-translation-files', the current XLIFF files[1].
|
||||
|
||||
|
||||
Creating XLIFF files from existing FlightGear legacy XML translation files
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
To get the initial XLIFF files (generated from the default translation in
|
||||
$FG_ROOT/Translations/default as well as the legacy FlightGear XML
|
||||
localization files in $FG_ROOT/Translations/<language_code>):
|
||||
|
||||
languages="de en_US es fr it nl pl pt zh_CN"
|
||||
|
||||
# Your shell must expand $languages as several words for the following
|
||||
# commands to work. POSIX shell does that, Bash too apparently, but not Zsh
|
||||
# (by default). In Zsh, you can use $=languages or ${=languages} to ensure
|
||||
# the expansion uses word splitting.
|
||||
fg-convert-translation-files --transl-dir="$FG_ROOT/Translations" $languages
|
||||
|
||||
# Add strings found in the default translation but missing in the legacy FG
|
||||
# XML l10n files
|
||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||
merge-new-master $languages
|
||||
|
||||
Updating XLIFF files to reflect changes in the default translation
|
||||
------------------------------------------------------------------
|
||||
|
||||
When master strings[2] have changed (in a large sense, i.e.: strings added,
|
||||
modified or removed, or categories added or removed[3]):
|
||||
|
||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||
merge-new-master $languages
|
||||
|
||||
Updating XLIFF files to mark or remove obsolete translated strings
|
||||
------------------------------------------------------------------
|
||||
|
||||
To remove unused translated strings (not to be done too often in my opinion):
|
||||
|
||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||
remove-unused $languages
|
||||
|
||||
(you may replace 'remove-unused' with 'mark-unused' to just mark the strings
|
||||
as not-to-be-translated, however 'merge-new-master' presented above already
|
||||
does that)
|
||||
|
||||
Merging contents from an XLIFF file into another one
|
||||
----------------------------------------------------
|
||||
|
||||
Suppose a translator has been working on a particular translation file, and
|
||||
meanwhile the official XLIFF file for this translation has been updated in
|
||||
FGData (new translatable strings added, obsolete strings marked or removed,
|
||||
etc.). In such a case, 'fg-merge-xliff-into-xliff' can be used to merge the
|
||||
translator's work into the project file. Essentially, this means that for all
|
||||
strings that have the same source text, plural status, number of plural forms
|
||||
and of course target language, the target texts, “approved” status and
|
||||
translator comments will be taken from the first file passed in the following
|
||||
command:
|
||||
|
||||
fg-merge-xliff-into-xliff TRANSLATOR_FILE PROJECT_FILE
|
||||
|
||||
Used like this, PROJECT_FILE will be updated with data from TRANSLATOR_FILE.
|
||||
If you don't want to modify PROJECT_FILE, use the -o (--output) option. If '-'
|
||||
is passed as argument to this option, then the result is written to the
|
||||
standard output.
|
||||
|
||||
Creating skeleton XLIFF files for new translations
|
||||
--------------------------------------------------
|
||||
|
||||
To create skeleton translations for new languages (e.g., for fr_BE, en_AU and
|
||||
ca):
|
||||
|
||||
1) Check (add if necessary) that flightgear/meta/i18n.py knows the plural
|
||||
forms used in the new languages. This is done by editing PLURAL_FORMS
|
||||
towards the top of this i18n.py file (very easy). If the existing entry
|
||||
for, e.g., "zh" is sufficient for zh_TW or zh_HK, just let "zh" handle
|
||||
them: it will be tried as fallback if there is no perfect match on
|
||||
language and territory.
|
||||
|
||||
2) Run a command such as:
|
||||
|
||||
fg-new-translations --transl-dir="$FG_ROOT/Translations" fr_BE en_AU ca
|
||||
|
||||
(if you do this for only one language at a time, you can use the -o
|
||||
option to precisely control where the output goes, otherwise
|
||||
fg-new-translations chooses an appropriate place based on the value
|
||||
specified for --transl-dir)
|
||||
|
||||
Getting more information on the scripts
|
||||
---------------------------------------
|
||||
|
||||
fg-convert-translation-files, fg-update-translation-files,
|
||||
fg-merge-xliff-into-xliff and fg-new-translations all support the --help
|
||||
option for more detailed information.
|
||||
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
|
||||
[1] Except for the fg-merge-xliff-into-xliff script, which doesn't have any
|
||||
of these requirements.
|
||||
|
||||
[2] Strings in the default translation.
|
||||
|
||||
[3] Only empty categories are removed by this command. An obsolete category
|
||||
can be made empty by manual editing (easy, just locate the right
|
||||
<group>) or this way:
|
||||
|
||||
fg-update-translation-files --transl-dir=... mark-unused
|
||||
fg-update-translation-files --transl-dir=... remove-unused
|
||||
|
||||
(note that this will remove *all* strings marked as unused in the first
|
||||
step, not only those in some particular category!)
|
||||
181
python3-flightgear/fg-convert-translation-files
Executable file
181
python3-flightgear/fg-convert-translation-files
Executable file
@@ -0,0 +1,181 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# fg-convert-translation-files --- Convert FlightGear's translation files
|
||||
# Copyright (C) 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import argparse
|
||||
import collections
|
||||
import locale
|
||||
import os
|
||||
import sys
|
||||
|
||||
import flightgear.meta.logging
|
||||
import flightgear.meta.i18n as fg_i18n
|
||||
|
||||
|
||||
PROGNAME = os.path.basename(sys.argv[0])
|
||||
|
||||
# Only messages with severity >= info will be printed to the terminal (it's
|
||||
# possible to also log all messages to a file regardless of their level, see
|
||||
# the Logger class). Of course, there is also the standard logging module...
|
||||
logger = flightgear.meta.logging.Logger(
|
||||
progname=PROGNAME,
|
||||
logLevel=flightgear.meta.logging.LogLevel.info,
|
||||
defaultOutputStream=sys.stderr)
|
||||
|
||||
debug = logger.debug
|
||||
info = logger.info
|
||||
notice = logger.notice
|
||||
warning = logger.warning
|
||||
error = logger.error
|
||||
critical = logger.critical
|
||||
|
||||
|
||||
# We could use Translation.__str__(): not as readable (for now) but more
|
||||
# accurate on metadata
|
||||
def printPlainText(l10nResPoolMgr, translations):
|
||||
"""Print output suitable for a quick review (by the programmer)."""
|
||||
firstLang = True
|
||||
|
||||
for langCode, (transl, nbWhitespacePbs) in translations.items():
|
||||
# 'transl' is a Translation instance
|
||||
if firstLang:
|
||||
firstLang = False
|
||||
else:
|
||||
print()
|
||||
|
||||
print("-" * 78 + "\n" + langCode + "\n" + "-" * 78)
|
||||
print("\nNumber of leading and/or trailing whitespace problems: {}"
|
||||
.format(nbWhitespacePbs))
|
||||
|
||||
for cat in transl:
|
||||
print("\nCategory: {cat}\n{underline}".format(
|
||||
cat=cat, underline="~"*(len("Category: ") + len(cat))))
|
||||
t = transl[cat]
|
||||
|
||||
for tid, translUnit in sorted(t.items()):
|
||||
# - Using '{master!r}' and '{transl!r}' prints stuff such as
|
||||
# \xa0 for nobreak spaces, which can lead to the erroneous
|
||||
# conclusion that there was an encoding problem.
|
||||
# - Only printing the first target text here (no plural forms)
|
||||
print("\n{id}\n '{sourceText}'\n '{targetText}'"
|
||||
.format(id=tid.id(), sourceText=translUnit.sourceText,
|
||||
targetText=translUnit.targetTexts[0]))
|
||||
|
||||
|
||||
def writeXliff(l10nResPoolMgr, translations):
|
||||
formatHandler = fg_i18n.XliffFormatHandler()
|
||||
|
||||
for langCode, translData in translations.items():
|
||||
translation = translData.transl # Translation instance
|
||||
|
||||
if params.output_dir is None:
|
||||
# Use default locations for the written xliff files
|
||||
l10nResPoolMgr.writeTranslation(formatHandler, translation)
|
||||
else:
|
||||
basename = "{}-{}.{}".format(
|
||||
formatHandler.defaultFileStem(langCode),
|
||||
langCode,
|
||||
formatHandler.standardExtension)
|
||||
filePath = os.path.join(params.output_dir, basename)
|
||||
formatHandler.writeTranslation(translation, filePath)
|
||||
|
||||
|
||||
def processCommandLine():
|
||||
params = argparse.Namespace()
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="""\
|
||||
%(prog)s [OPTION ...] LANGUAGE_CODE...
|
||||
Convert FlightGear's old XML translation files into other formats.""",
|
||||
description="""\
|
||||
Most notably, XLIFF format can be chosen for output. The script performs
|
||||
a few automated checks on the input files too.""",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# I want --help but not -h (it might be useful for something else)
|
||||
add_help=False)
|
||||
|
||||
parser.add_argument("-t", "--transl-dir",
|
||||
help="""\
|
||||
directory containing all translation subdirs (such as
|
||||
{default!r}, 'en_GB', 'fr_FR', 'de', 'it'...). This
|
||||
"option" MUST be specified.""".format(
|
||||
default=fg_i18n.DEFAULT_LANG_DIR))
|
||||
parser.add_argument("lang_code", metavar="LANGUAGE_CODE", nargs="+",
|
||||
help="""\
|
||||
codes of languages to read translations for (don't
|
||||
specify {default!r} this way, it is special and not a
|
||||
language code)"""
|
||||
.format(default=fg_i18n.DEFAULT_LANG_DIR))
|
||||
parser.add_argument("-o", "--output-dir",
|
||||
help="""\
|
||||
output directory for written XLIFF files
|
||||
(default: for each output file, use a suitable location
|
||||
under TRANSL_DIR)""")
|
||||
parser.add_argument("-f", "--output-format", default="xliff",
|
||||
choices=("xliff", "text"), help="""\
|
||||
format to use for the output files""")
|
||||
parser.add_argument("--help", action="help",
|
||||
help="display this message and exit")
|
||||
|
||||
params = parser.parse_args(namespace=params)
|
||||
|
||||
if params.transl_dir is None:
|
||||
error("--transl-dir must be given, aborting")
|
||||
sys.exit(1)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def main():
|
||||
global params
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
params = processCommandLine()
|
||||
|
||||
l10nResPoolMgr = fg_i18n.L10NResourcePoolManager(params.transl_dir, logger)
|
||||
# English version of all translatable strings
|
||||
masterTransl, nbWhitespaceProblemsInMaster = \
|
||||
l10nResPoolMgr.readFgMasterTranslation()
|
||||
translations = collections.OrderedDict()
|
||||
|
||||
# Sort elements of 'translations' according to language code (= the keys)
|
||||
for langCode in sorted(params.lang_code):
|
||||
translationData = l10nResPoolMgr.readFgTranslation(masterTransl,
|
||||
langCode)
|
||||
translations[translationData.transl.targetLanguage] = translationData
|
||||
|
||||
if params.output_format == "xliff":
|
||||
writeFunc = writeXliff # write to files
|
||||
elif params.output_format == "text":
|
||||
writeFunc = printPlainText # print to stdout
|
||||
else:
|
||||
assert False, \
|
||||
"Unexpected output format: '{}'".format(params.output_format)
|
||||
|
||||
writeFunc(l10nResPoolMgr, translations)
|
||||
|
||||
nbWhitespaceProblemsInTransl = sum(
|
||||
(translData.nbWhitespacePbs for translData in translations.values() ))
|
||||
info("total number of leading and/or trailing whitespace problems: {}"
|
||||
.format(nbWhitespaceProblemsInMaster + nbWhitespaceProblemsInTransl))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
123
python3-flightgear/fg-merge-xliff-into-xliff
Executable file
123
python3-flightgear/fg-merge-xliff-into-xliff
Executable file
@@ -0,0 +1,123 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# fg-merge-xliff-into-xliff --- Merge translations from one XLIFF file into
|
||||
# another one
|
||||
# Copyright (C) 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import argparse
|
||||
import locale
|
||||
import os
|
||||
import sys
|
||||
|
||||
import flightgear.meta.logging
|
||||
import flightgear.meta.i18n as fg_i18n
|
||||
|
||||
|
||||
PROGNAME = os.path.basename(sys.argv[0])
|
||||
|
||||
# Only messages with severity >= info will be printed to the terminal (it's
|
||||
# possible to also log all messages to a file regardless of their level, see
|
||||
# the Logger class). Of course, there is also the standard logging module...
|
||||
logger = flightgear.meta.logging.Logger(
|
||||
progname=PROGNAME,
|
||||
logLevel=flightgear.meta.logging.LogLevel.info,
|
||||
defaultOutputStream=sys.stderr)
|
||||
|
||||
|
||||
def processCommandLine():
|
||||
params = argparse.Namespace()
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="""\
|
||||
%(prog)s [OPTION ...] SOURCE INTO
|
||||
Merge strings from a FlightGear XLIFF localization file into another one.""",
|
||||
description="""\
|
||||
This program merges a FlightGear XLIFF localization file into another one.
|
||||
This means that every translatable string that:
|
||||
|
||||
(1) exists in both SOURCE and INTO;
|
||||
|
||||
(2) has the same target language, source text, plural status and number of
|
||||
plural forms in SOURCE and in INTO;
|
||||
|
||||
is updated from SOURCE, i.e.: the target texts, 'approved' status and
|
||||
translator comments are copied from SOURCE.
|
||||
|
||||
The result is written to INTO unless the -o (--output) option is given.
|
||||
|
||||
Note that this program is different from fg-update-translation-files's
|
||||
'merge-new-master' command, which is for updating an XLIFF file according to
|
||||
the default translation ("master").
|
||||
|
||||
Expected use case: suppose that a translator is working on a translation
|
||||
file, and meanwhile the official XLIFF file for this translation is updated
|
||||
in the project repository (new translatable strings added, obsolete strings
|
||||
marked or removed, etc.). This program can then be used to merge the
|
||||
translator work into the project file for all strings for which it makes
|
||||
sense (source text unchanged, same plural status, etc.).""",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# I want --help but not -h (it might be useful for something else)
|
||||
add_help=False)
|
||||
|
||||
parser.add_argument("source", metavar="SOURCE",
|
||||
help="""\
|
||||
input XLIFF file; read updated translated strings
|
||||
from this file""")
|
||||
parser.add_argument("into", metavar="INTO",
|
||||
help="""\
|
||||
XLIFF file to compare to SOURCE in order to decide
|
||||
which translated strings to update; unless the -o
|
||||
option is used, updated strings are written to this
|
||||
file""")
|
||||
parser.add_argument("-o", "--output",
|
||||
help="""\
|
||||
write the XLIFF merged output to OUTPUT instead of
|
||||
INTO. When this option is used, INTO is read but not
|
||||
modified. If OUTPUT is '-', write the XLIFF merged
|
||||
output to the standard output.""")
|
||||
parser.add_argument("--help", action="help",
|
||||
help="display this message and exit")
|
||||
|
||||
return parser.parse_args(namespace=params)
|
||||
|
||||
|
||||
def mergeXliffIntoXliff(source, into, output):
|
||||
formatHandler = fg_i18n.XliffFormatHandler()
|
||||
|
||||
srcTransl = formatHandler.readTranslation(source)
|
||||
transl = formatHandler.readTranslation(into)
|
||||
# Merge 'srcTransl' into 'transl'
|
||||
transl.mergeNonMasterTransl(srcTransl, logger=logger)
|
||||
|
||||
# File path, or '-' for the standard output
|
||||
outputFile = into if output is None else output
|
||||
formatHandler.writeTranslation(transl, outputFile)
|
||||
|
||||
|
||||
def main():
|
||||
global params
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
params = processCommandLine()
|
||||
|
||||
mergeXliffIntoXliff(params.source, params.into, params.output)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
120
python3-flightgear/fg-new-translations
Executable file
120
python3-flightgear/fg-new-translations
Executable file
@@ -0,0 +1,120 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# fg-new-translations --- Create new translations for FlightGear
|
||||
# Copyright (C) 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import argparse
|
||||
import collections
|
||||
import locale
|
||||
import os
|
||||
import sys
|
||||
|
||||
import flightgear.meta.logging
|
||||
import flightgear.meta.i18n as fg_i18n
|
||||
|
||||
|
||||
PROGNAME = os.path.basename(sys.argv[0])
|
||||
|
||||
# Only messages with severity >= info will be printed to the terminal (it's
|
||||
# possible to also log all messages to a file regardless of their level, see
|
||||
# the Logger class). Of course, there is also the standard logging module...
|
||||
logger = flightgear.meta.logging.Logger(
|
||||
progname=PROGNAME,
|
||||
logLevel=flightgear.meta.logging.LogLevel.info,
|
||||
defaultOutputStream=sys.stderr)
|
||||
|
||||
|
||||
def processCommandLine():
|
||||
params = argparse.Namespace()
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="""\
|
||||
%(prog)s [OPTION ...] LANGUAGE_CODE...
|
||||
Write the skeleton of XLIFF translation files.""",
|
||||
description="""\
|
||||
This program writes XLIFF translation files with the strings to translate
|
||||
for the specified languages (target strings are empty). This is what you need
|
||||
to start a translation for a new language.""",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# I want --help but not -h (it might be useful for something else)
|
||||
add_help=False)
|
||||
|
||||
parser.add_argument("-t", "--transl-dir",
|
||||
help="""\
|
||||
directory containing all translation subdirs (such as
|
||||
{default!r}, 'en_GB', 'fr_FR', 'de', 'it'...). This
|
||||
"option" MUST be specified.""".format(
|
||||
default=fg_i18n.DEFAULT_LANG_DIR))
|
||||
parser.add_argument("lang_code", metavar="LANGUAGE_CODE", nargs="+",
|
||||
help="""\
|
||||
codes of languages to create translations for (e.g., fr,
|
||||
fr_BE, en_GB, it, es_ES...)""")
|
||||
parser.add_argument("-o", "--output-file",
|
||||
help="""\
|
||||
where to write the output to (use '-' for standard
|
||||
output); if not specified, a suitable file under
|
||||
TRANSL_DIR will be chosen for each LANGUAGE_CODE.
|
||||
Note: this option can only be given when exactly one
|
||||
LANGUAGE_CODE has been specified on the command
|
||||
line (it doesn't make sense otherwise).""")
|
||||
parser.add_argument("--output-format", default="xliff",
|
||||
choices=fg_i18n.FORMAT_HANDLERS_NAMES,
|
||||
help="format to use for the output files")
|
||||
parser.add_argument("--help", action="help",
|
||||
help="display this message and exit")
|
||||
|
||||
params = parser.parse_args(namespace=params)
|
||||
|
||||
if params.transl_dir is None:
|
||||
logger.error("--transl-dir must be given, aborting")
|
||||
sys.exit(1)
|
||||
|
||||
if params.output_file is not None and len(params.lang_code) > 1:
|
||||
logger.error("--output-file can only be given when exactly one "
|
||||
"LANGUAGE_CODE has been specified on the command line "
|
||||
"(it doesn't make sense otherwise)")
|
||||
sys.exit(1)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def main():
|
||||
global params
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
params = processCommandLine()
|
||||
|
||||
l10nResPoolMgr = fg_i18n.L10NResourcePoolManager(params.transl_dir, logger)
|
||||
xliffFormatHandler = fg_i18n.FORMAT_HANDLERS_MAP[params.output_format]()
|
||||
|
||||
if params.output_file is not None:
|
||||
assert len(params.lang_code) == 1, params.lang_code
|
||||
# Output to one file or to stdout
|
||||
l10nResPoolMgr.writeSkeletonTranslation(
|
||||
xliffFormatHandler, params.lang_code[0],
|
||||
filePath=params.output_file)
|
||||
else:
|
||||
# Output to several files
|
||||
for langCode in params.lang_code:
|
||||
l10nResPoolMgr.writeSkeletonTranslation(xliffFormatHandler,
|
||||
langCode)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
179
python3-flightgear/fg-update-translation-files
Executable file
179
python3-flightgear/fg-update-translation-files
Executable file
@@ -0,0 +1,179 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# fg-update-translation-files --- Merge new default translation,
|
||||
# remove obsolete strings from a translation
|
||||
# Copyright (C) 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import argparse
|
||||
import enum
|
||||
import locale
|
||||
import os
|
||||
import sys
|
||||
|
||||
import flightgear.meta.logging
|
||||
import flightgear.meta.i18n as fg_i18n
|
||||
|
||||
|
||||
PROGNAME = os.path.basename(sys.argv[0])
|
||||
|
||||
# Only messages with severity >= info will be printed to the terminal (it's
|
||||
# possible to also log all messages to a file regardless of their level, see
|
||||
# the Logger class). Of course, there is also the standard logging module...
|
||||
logger = flightgear.meta.logging.Logger(
|
||||
progname=PROGNAME,
|
||||
logLevel=flightgear.meta.logging.LogLevel.info,
|
||||
defaultOutputStream=sys.stderr)
|
||||
|
||||
|
||||
def processCommandLine():
|
||||
params = argparse.Namespace()
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="""\
|
||||
%(prog)s [OPTION ...] ACTION LANGUAGE_CODE...
|
||||
Update FlightGear XLIFF localization files.""",
|
||||
description="""\
|
||||
This program performs the following operations (actions) on FlightGear XLIFF
|
||||
translation files (*.xlf):
|
||||
|
||||
- [merge-new-master]
|
||||
Read the default translation[1], add new translated strings it contains to
|
||||
the XLIFF localization files corresponding to the specified language(s),
|
||||
mark the translated strings in said files that need review (modified in
|
||||
the default translation) as well as those that are not used anymore
|
||||
(disappeared in the default translation, or marked in a way that says they
|
||||
don't need to be translated);
|
||||
|
||||
- [mark-unused]
|
||||
Read the default translation and mark translated strings (in the XLIFF
|
||||
localization files corresponding to the specified language(s)) that are
|
||||
not used anymore;
|
||||
|
||||
- [remove-unused]
|
||||
In the XLIFF localization files corresponding to the specified
|
||||
language(s), remove all translated strings that are marked as unused.
|
||||
|
||||
A translated string that is marked as unused is still present in the XLIFF
|
||||
localization file; it is just presented in a way that tells translators they
|
||||
don't need to worry about it. On the other hand, when a translated string is
|
||||
removed, translators don't see it anymore and the translation is lost, except
|
||||
if rescued by external means such as backups or version control systems (Git,
|
||||
Subversion, etc.)
|
||||
|
||||
Note that the 'remove-unused' action does *not* imply 'mark-unused'. It only
|
||||
removes translation units that are already marked as unused (i.e., with
|
||||
translate="no"). Thus, it makes sense to do 'mark-unused' followed by
|
||||
'remove-unused' if you really want to get rid of old translations (you need to
|
||||
invoke the program twice, or make a small change for this). Leaving unused
|
||||
translated strings marked as such in XLIFF files shouldn't harm much in
|
||||
general on the short or mid-term: they only take some space.
|
||||
|
||||
[1] FlightGear XML files in $FG_ROOT/Translations/default containing strings
|
||||
used for the default locale (English).""",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# I want --help but not -h (it might be useful for something else)
|
||||
add_help=False)
|
||||
|
||||
parser.add_argument("-t", "--transl-dir",
|
||||
help="""\
|
||||
directory containing all translation subdirs (such as
|
||||
{default!r}, 'en_GB', 'fr_FR', 'de', 'it'...). This
|
||||
"option" MUST be specified.""".format(
|
||||
default=fg_i18n.DEFAULT_LANG_DIR))
|
||||
parser.add_argument("action", metavar="ACTION",
|
||||
choices=("merge-new-master",
|
||||
"mark-unused",
|
||||
"remove-unused"),
|
||||
help="""\
|
||||
what to do: merge a new default (= master)
|
||||
translation, or mark unused translation units, or
|
||||
remove those already marked as unused from the XLIFF
|
||||
files corresponding to each given LANGUAGE_CODE (i.e.,
|
||||
those that are not in the default translation)""")
|
||||
parser.add_argument("lang_code", metavar="LANGUAGE_CODE", nargs="+",
|
||||
help="""\
|
||||
codes of languages to operate on (e.g., fr, en_GB, it,
|
||||
es_ES...)""")
|
||||
parser.add_argument("--help", action="help",
|
||||
help="display this message and exit")
|
||||
|
||||
params = parser.parse_args(namespace=params)
|
||||
|
||||
if params.transl_dir is None:
|
||||
logger.error("--transl-dir must be given, aborting")
|
||||
sys.exit(1)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
class MarkOrRemoveUnusedAction(enum.Enum):
|
||||
mark, remove = range(2)
|
||||
|
||||
|
||||
def markOrRemoveUnused(l10nResPoolMgr, action):
|
||||
formatHandler = fg_i18n.XliffFormatHandler()
|
||||
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
||||
|
||||
for langCode in params.lang_code:
|
||||
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
||||
transl = formatHandler.readTranslation(xliffPath)
|
||||
|
||||
if action == MarkOrRemoveUnusedAction.mark:
|
||||
transl.markObsoleteOrVanished(masterTransl, logger=logger)
|
||||
elif action == MarkOrRemoveUnusedAction.remove:
|
||||
transl.removeObsoleteOrVanished(logger=logger)
|
||||
else:
|
||||
assert False, "unexpected action: {!r}".format(action)
|
||||
|
||||
l10nResPoolMgr.writeTranslation(formatHandler, transl,
|
||||
filePath=xliffPath)
|
||||
|
||||
|
||||
def mergeNewMaster(l10nResPoolMgr):
|
||||
formatHandler = fg_i18n.XliffFormatHandler()
|
||||
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
||||
|
||||
for langCode in params.lang_code:
|
||||
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
||||
transl = formatHandler.readTranslation(xliffPath)
|
||||
transl.mergeMasterTranslation(masterTransl, logger=logger)
|
||||
l10nResPoolMgr.writeTranslation(formatHandler, transl,
|
||||
filePath=xliffPath)
|
||||
|
||||
|
||||
def main():
|
||||
global params
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
params = processCommandLine()
|
||||
|
||||
l10nResPoolMgr = fg_i18n.L10NResourcePoolManager(params.transl_dir, logger)
|
||||
|
||||
if params.action == "mark-unused":
|
||||
markOrRemoveUnused(l10nResPoolMgr, MarkOrRemoveUnusedAction.mark)
|
||||
elif params.action == "remove-unused":
|
||||
markOrRemoveUnused(l10nResPoolMgr, MarkOrRemoveUnusedAction.remove)
|
||||
elif params.action == "merge-new-master":
|
||||
mergeNewMaster(l10nResPoolMgr)
|
||||
else:
|
||||
assert False, "Bug: unexpected action: {!r}".format(params.action)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
0
python3-flightgear/flightgear/__init__.py
Normal file
0
python3-flightgear/flightgear/__init__.py
Normal file
0
python3-flightgear/flightgear/meta/__init__.py
Normal file
0
python3-flightgear/flightgear/meta/__init__.py
Normal file
58
python3-flightgear/flightgear/meta/exceptions.py
Normal file
58
python3-flightgear/flightgear/meta/exceptions.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# exceptions.py --- Simple, general-purpose subclass of Exception
|
||||
#
|
||||
# Copyright (C) 2015, 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
"""Simple, general-purpose Exception subclass."""
|
||||
|
||||
|
||||
class FGPyException(Exception):
|
||||
def __init__(self, message=None, *, mayCapitalizeMsg=True):
|
||||
"""Initialize an FGPyException instance.
|
||||
|
||||
Except in cases where 'message' starts with a proper noun or
|
||||
something like that, its first character should be given in
|
||||
lower case. Automated treatments of this exception may print the
|
||||
message with its first character changed to upper case, unless
|
||||
'mayCapitalizeMsg' is False. In other words, if the case of the
|
||||
first character of 'message' must not be changed under any
|
||||
circumstances, set 'mayCapitalizeMsg' to False.
|
||||
|
||||
"""
|
||||
self.message = message
|
||||
self.mayCapitalizeMsg = mayCapitalizeMsg
|
||||
|
||||
def __str__(self):
|
||||
return self.completeMessage()
|
||||
|
||||
def __repr__(self):
|
||||
return "{}.{}({!r})".format(__name__, type(self).__name__, self.message)
|
||||
|
||||
# Typically overridden by subclasses with a custom constructor
|
||||
def detail(self):
|
||||
return self.message
|
||||
|
||||
def completeMessage(self):
|
||||
if self.message:
|
||||
return "{shortDesc}: {detail}".format(
|
||||
shortDesc=self.ExceptionShortDescription,
|
||||
detail=self.detail())
|
||||
else:
|
||||
return self.ExceptionShortDescription
|
||||
|
||||
ExceptionShortDescription = "FlightGear Python generic exception"
|
||||
1925
python3-flightgear/flightgear/meta/i18n.py
Normal file
1925
python3-flightgear/flightgear/meta/i18n.py
Normal file
File diff suppressed because it is too large
Load Diff
95
python3-flightgear/flightgear/meta/logging.py
Normal file
95
python3-flightgear/flightgear/meta/logging.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# logging.py --- Simple logging infrastructure (mostly taken from FFGo)
|
||||
# Copyright (C) 2015, 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import sys
|
||||
|
||||
from . import misc
|
||||
|
||||
|
||||
class LogLevel(misc.OrderedEnum):
|
||||
debug, info, notice, warning, error, critical = range(6)
|
||||
|
||||
# List containing the above log levels as strings in increasing priority order
|
||||
allLogLevels = [member.name for member in LogLevel]
|
||||
allLogLevels.sort(key=lambda n: LogLevel[n].value)
|
||||
|
||||
|
||||
def _logFuncFactory(level):
|
||||
def logFunc(self, *args, **kwargs):
|
||||
self.log(LogLevel[level], True, *args, **kwargs)
|
||||
|
||||
def logFunc_noPrefix(self, *args, **kwargs):
|
||||
self.log(LogLevel[level], False, *args, **kwargs)
|
||||
|
||||
return (logFunc, logFunc_noPrefix)
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self, progname=None, logLevel=LogLevel.notice,
|
||||
defaultOutputStream=sys.stdout, logFile=None):
|
||||
self.progname = progname
|
||||
self.logLevel = logLevel
|
||||
self.defaultOutputStream = defaultOutputStream
|
||||
self.logFile = logFile
|
||||
|
||||
def setLogFile(self, *args, **kwargs):
|
||||
self.logFile = open(*args, **kwargs)
|
||||
|
||||
def log(self, level, printLogLevel, *args, **kwargs):
|
||||
if printLogLevel and level >= LogLevel.warning and args:
|
||||
args = [level.name.upper() + ": " + args[0]] + list(args[1:])
|
||||
|
||||
if level >= self.logLevel:
|
||||
if (self.progname is not None) and args:
|
||||
tArgs = [self.progname + ": " + args[0]] + list(args[1:])
|
||||
else:
|
||||
tArgs = args
|
||||
|
||||
kwargs["file"] = self.defaultOutputStream
|
||||
print(*tArgs, **kwargs)
|
||||
|
||||
if self.logFile is not None:
|
||||
kwargs["file"] = self.logFile
|
||||
print(*args, **kwargs)
|
||||
|
||||
# Don't overload log() with too many tests or too much indirection for
|
||||
# little use
|
||||
def logToFile(self, *args, **kwargs):
|
||||
kwargs["file"] = self.logFile
|
||||
print(*args, **kwargs)
|
||||
|
||||
# NP functions are “no prefix” variants which never prepend the log level
|
||||
# (otherwise, it is only prepended for warning and higher levels).
|
||||
debug, debugNP = _logFuncFactory("debug")
|
||||
info, infoNP = _logFuncFactory("info")
|
||||
notice, noticeNP = _logFuncFactory("notice")
|
||||
warning, warningNP = _logFuncFactory("warning")
|
||||
error, errorNP = _logFuncFactory("error")
|
||||
critical, criticalNP = _logFuncFactory("critical")
|
||||
|
||||
|
||||
class DummyLogger(Logger):
|
||||
def setLogFile(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def log(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def logToFile(self, *args, **kwargs):
|
||||
pass
|
||||
81
python3-flightgear/flightgear/meta/misc.py
Normal file
81
python3-flightgear/flightgear/meta/misc.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# misc.py --- Miscellaneous classes and/or functions
|
||||
# Copyright (C) 2015-2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import enum
|
||||
|
||||
# Based on an example from the 'enum' documentation
|
||||
class OrderedEnum(enum.Enum):
|
||||
"""Base class for enumerations whose members can be ordered.
|
||||
|
||||
Contrary to enum.IntEnum, this class maintains normal enum.Enum
|
||||
invariants, such as members not being comparable to members of other
|
||||
enumerations (nor of any other class, actually).
|
||||
|
||||
"""
|
||||
def __ge__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value >= other.value
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value > other.value
|
||||
return NotImplemented
|
||||
|
||||
def __le__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value <= other.value
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value < other.value
|
||||
return NotImplemented
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value == other.value
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
if self.__class__ is other.__class__:
|
||||
return self.value != other.value
|
||||
return NotImplemented
|
||||
|
||||
|
||||
# Taken from <http://effbot.org/zone/element-lib.htm#prettyprint> and modified
|
||||
# by Florent Rougon
|
||||
def indentXmlTree(elem, level=0, basicOffset=2, lastChild=False):
|
||||
def indentation(level):
|
||||
return "\n" + level*basicOffset*" "
|
||||
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = indentation(level+1)
|
||||
|
||||
for e in elem[:-1]:
|
||||
indentXmlTree(e, level+1, basicOffset, False)
|
||||
if len(elem):
|
||||
indentXmlTree(elem[-1], level+1, basicOffset, True)
|
||||
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
if lastChild:
|
||||
elem.tail = indentation(level-1)
|
||||
else:
|
||||
elem.tail = indentation(level)
|
||||
172
python3-flightgear/rebuild-fgdata-embedded-resources
Executable file
172
python3-flightgear/rebuild-fgdata-embedded-resources
Executable file
@@ -0,0 +1,172 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# rebuild-fgdata-embedded-resources -- Rebuild FGData-resources.[ch]xx
|
||||
# Copyright (C) 2017 Florent Rougon
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Only standard modules so that distributors can easily run this script, in
|
||||
# case they want to recreate FGData-resources.[ch]xx from source.
|
||||
import argparse
|
||||
import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
PROGNAME = os.path.basename(sys.argv[0])
|
||||
CONFIG_FILE = os.path.join(os.path.expanduser('~'),
|
||||
".fgmeta",
|
||||
PROGNAME + ".json")
|
||||
|
||||
# chLevel: console handler level
|
||||
def setupLogging(level=logging.NOTSET, chLevel=None):
|
||||
global logger
|
||||
|
||||
if chLevel is None:
|
||||
chLevel = level
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# Effective level for all child loggers with NOTSET level
|
||||
logger.setLevel(level)
|
||||
# Create console handler and set its level
|
||||
ch = logging.StreamHandler() # Uses sys.stderr by default
|
||||
ch.setLevel(chLevel) # NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||
# Logger name with :%(name)s... many other things available, including
|
||||
# %(levelname)s
|
||||
formatter = logging.Formatter("{}: %(message)s".format(PROGNAME))
|
||||
# Add formatter to ch
|
||||
ch.setFormatter(formatter)
|
||||
# Add ch to logger
|
||||
logger.addHandler(ch)
|
||||
|
||||
|
||||
# Modifies 'params' in-place
|
||||
def loadCfgFileSection(params, jsonTree, title, items):
|
||||
# NB: !!! each item is subject to os.path.expanduser() !!!
|
||||
try:
|
||||
section = jsonTree[title]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
for name in items:
|
||||
try:
|
||||
path = section[name]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
setattr(params, name.lower(), os.path.expanduser(path))
|
||||
|
||||
|
||||
# Modifies 'params' in-place
|
||||
def loadConfigFile(params):
|
||||
if not os.path.isfile(CONFIG_FILE):
|
||||
return
|
||||
|
||||
# The log level is set too late for this one -> commented out
|
||||
# logger.info("Loading config file {}...".format(CONFIG_FILE))
|
||||
|
||||
with open(CONFIG_FILE, "r", encoding="utf-8") as cfgFile:
|
||||
tree = json.load(cfgFile)
|
||||
|
||||
loadCfgFileSection(params, tree, "repositories", ("FlightGear", "FGData"))
|
||||
loadCfgFileSection(params, tree, "executables", ("fgrcc",))
|
||||
|
||||
|
||||
def processCommandLine(params):
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="""\
|
||||
%(prog)s [OPTION ...]
|
||||
Rebuild FGData embedded resources for FlightGear.""",
|
||||
description="""\
|
||||
|
||||
Use fgrcc with FGData-resources.xml and the corresponding files in FGData to
|
||||
(re)create the FGData-resources.[ch]xx files used in the FlightGear build. The
|
||||
existing files in the FlightGear repository are always overwritten
|
||||
(FGData-resources.[ch]xx in <FlightGear-repo>/src/EmbeddedResources).
|
||||
|
||||
This is a dumb script that simply calls fgrcc with appropriate parameters. In
|
||||
order to save some typing, you may want to use a configuration file like this
|
||||
(~/.fgmeta/%(prog)s.json):
|
||||
|
||||
{"repositories": {"FlightGear": "~/flightgear/src/flightgear",
|
||||
"FGData": "~/flightgear/src/fgdata"},
|
||||
"executables": {"fgrcc":
|
||||
"~/flightgear/src/build-fg/src/EmbeddedResources/fgrcc"
|
||||
}
|
||||
}""",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# I want --help but not -h (it might be useful for something else)
|
||||
add_help=False)
|
||||
|
||||
parser.add_argument('--flightgear', action='store', help="""\
|
||||
Path to the FlightGear repository""")
|
||||
parser.add_argument('--fgdata', action='store', help="""\
|
||||
Path to the FGData repository""")
|
||||
parser.add_argument('--fgrcc', action='store', help="""\
|
||||
Path to the fgrcc executable""")
|
||||
parser.add_argument('--log-level', action='store',
|
||||
choices=("debug", "info", "warning", "error",
|
||||
"critical"),
|
||||
default=None, help="""Set the log level""")
|
||||
parser.add_argument('--help', action="help",
|
||||
help="display this message and exit")
|
||||
|
||||
parser.parse_args(namespace=params)
|
||||
|
||||
# Don't use the 'default' argparse mechanism for this, in order to allow
|
||||
# the config file to set the log level in a meaningful way if we want (not
|
||||
# implemented at the time of this writing).
|
||||
if params.log_level is not None:
|
||||
logger.setLevel(getattr(sys.modules["logging"],
|
||||
params.log_level.upper()))
|
||||
|
||||
|
||||
def main():
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
setupLogging(level=logging.INFO) # may be overridden by options
|
||||
|
||||
params = argparse.Namespace()
|
||||
loadConfigFile(params) # could set the log level
|
||||
processCommandLine(params)
|
||||
|
||||
if (params.flightgear is None or params.fgdata is None or
|
||||
params.fgrcc is None):
|
||||
logger.error(
|
||||
"--flightgear, --fgdata and --fgrcc must all be specified (they "
|
||||
"may be set in the config file; use --help for more info)")
|
||||
sys.exit(1)
|
||||
|
||||
resDir = os.path.join(params.flightgear, "src", "EmbeddedResources")
|
||||
inputXMLFile = os.path.join(resDir, "FGData-resources.xml")
|
||||
cxxFile = os.path.join(resDir, "FGData-resources.cxx")
|
||||
hxxFile = os.path.join(resDir, "FGData-resources.hxx")
|
||||
args = [params.fgrcc,
|
||||
"--root={}".format(params.fgdata),
|
||||
"--output-cpp-file={}".format(cxxFile),
|
||||
"--init-func-name=initFGDataEmbeddedResources",
|
||||
"--output-header-file={}".format(hxxFile),
|
||||
"--output-header-identifier=_FG_FGDATA_EMBEDDED_RESOURCES",
|
||||
inputXMLFile]
|
||||
|
||||
# encoding="utf-8" requires Python >= 3.6 -> will add it later
|
||||
# (it's not really needed, as we don't process the output)
|
||||
subprocess.run(args, check=True)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
71
release_builder/create-release-branch-for.sh
Executable file
71
release_builder/create-release-branch-for.sh
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
#This file is part of FlightGear
|
||||
#
|
||||
#FlightGear is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU General Public License as published by
|
||||
#the Free Software Foundation, either version 2 of the License, or
|
||||
#(at your option) any later version.
|
||||
#
|
||||
#FlightGear 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 General Public License for more details.
|
||||
#
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with FlightGear If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if [ -z "$1" -o -z "$2" ]; then
|
||||
echo "usage: thismajor.thisminor nextmajor.nextminor path"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
IFS='.' read -r -a VERSION_A <<< "$1"
|
||||
shift
|
||||
if [ ${#VERSION_A[@]} != 2 ]; then
|
||||
echo "Need version as 'number.number'"
|
||||
exit
|
||||
fi
|
||||
THIS_MAJOR_VERSION=${VERSION_A[0]}
|
||||
THIS_MINOR_VERSION=${VERSION_A[1]}
|
||||
RELEASE_BRANCH="release/${THIS_MAJOR_VERSION}.${THIS_MINOR_VERSION}"
|
||||
|
||||
IFS='.' read -r -a VERSION_A <<< "$1"
|
||||
shift
|
||||
if [ ${#VERSION_A[@]} != 2 ]; then
|
||||
echo "Need version as 'number.number'"
|
||||
exit
|
||||
fi
|
||||
NEXT_MAJOR_VERSION=${VERSION_A[0]}
|
||||
NEXT_MINOR_VERSION=${VERSION_A[1]}
|
||||
|
||||
setVersionTo() {
|
||||
local V="$1"
|
||||
echo "setting version to $V"
|
||||
echo "$V" > version
|
||||
git add version
|
||||
echo "new version: $V" | git commit --file=-
|
||||
git tag "version/$V"
|
||||
}
|
||||
|
||||
createBranch() {
|
||||
echo "Preparing release in `pwd`"
|
||||
|
||||
git checkout next
|
||||
git pull --rebase
|
||||
|
||||
setVersionTo "${THIS_MAJOR_VERSION}.${THIS_MINOR_VERSION}.1"
|
||||
|
||||
echo "Creating branch $RELEASE_BRANCH for version $(cat version) in `pwd`"
|
||||
git branch "$RELEASE_BRANCH"
|
||||
|
||||
setVersionTo "${NEXT_MAJOR_VERSION}.${NEXT_MINOR_VERSION}.0"
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
echo "Processing $1"
|
||||
pushd $1 > /dev/null
|
||||
createBranch
|
||||
popd > /dev/null
|
||||
shift
|
||||
done
|
||||
44
release_builder/create-release-branch.sh
Executable file
44
release_builder/create-release-branch.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
THIS_RELEASE="2018.2"
|
||||
NEXT_RELEASE="2018.3"
|
||||
SUBMODULES="simgear flightgear fgdata getstart"
|
||||
|
||||
#:<< 'COMMENT_END'
|
||||
git checkout next
|
||||
git pull --rebase
|
||||
|
||||
$(dirname $0)/create-release-branch-for.sh "$THIS_RELEASE" "$NEXT_RELEASE" $SUBMODULES .
|
||||
|
||||
# use release branch for submodules
|
||||
git checkout release/${THIS_RELEASE}
|
||||
for f in $SUBMODULES; do
|
||||
git config -f .gitmodules submodule.${f}.branch release/${THIS_RELEASE}
|
||||
done
|
||||
git add .gitmodules && echo "set correct release-branch for submodules" | git commit --file=-
|
||||
|
||||
# track submodule changes
|
||||
git checkout next
|
||||
git add $SUBMODULES && echo "track submodule changes for release" | git commit --file=-
|
||||
#COMMENT_END
|
||||
|
||||
echo "Check this and submodules $SUBMODULES - hit <enter> to push or <ctrl-c> to cancel"
|
||||
read something
|
||||
|
||||
for f in $SUBMODULES .; do
|
||||
pushd "$f"
|
||||
echo "Pushing $f"
|
||||
git checkout release/${THIS_RELEASE} && git push origin release/${THIS_RELEASE} && git push origin version/${THIS_RELEASE}.1 && git push origin version/${NEXT_RELEASE}.0 && git checkout next && git push
|
||||
popd
|
||||
done
|
||||
|
||||
#this needs ~/.ssh/config to contain this
|
||||
#HOST sf svn.code.sf.net
|
||||
# HOSTNAME svn.code.sf.net
|
||||
# IdentityFile ~/.ssh/your_sf_keyfile
|
||||
# IdentitiesOnly yes
|
||||
# User user_sf_username
|
||||
|
||||
svn copy svn+ssh://svn.code.sf.net/p/flightgear/fgaddon/trunk \
|
||||
svn+ssh://svn.code.sf.net/p/flightgear/fgaddon/branches/release-${THIS_RELEASE} \
|
||||
-m "branching for release ${THIS_RELEASE}"
|
||||
2
simgear
2
simgear
Submodule simgear updated: 09ab029e2f...7dd20f0174
@@ -1,41 +0,0 @@
|
||||
|
||||
import subprocess, os, sgprops
|
||||
import xml.etree.cElementTree as ET
|
||||
|
||||
class SVNCatalogRepository:
|
||||
def __init__(self, node):
|
||||
path = node.getValue("path")
|
||||
if not os.path.exists(path):
|
||||
raise RuntimeError("No directory at:" + path)
|
||||
|
||||
self._path = path
|
||||
xml = subprocess.check_output(["svn", "info", "--xml", path])
|
||||
root = ET.fromstring(xml)
|
||||
|
||||
if (root.find(".//repository/root") == None):
|
||||
raise RuntimeError("Not an SVN repository:" + path)
|
||||
|
||||
self._aircraftPath = None
|
||||
if node.hasChild("scan-suffix"):
|
||||
self._aircraftPath = os.path.join(path, node.getValue("scan-suffix"))
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def aircraftPath(self):
|
||||
return self._aircraftPath
|
||||
|
||||
def hasPathChanged(self, path, oldRevision):
|
||||
return self.scmRevisionForPath(path) != oldRevision
|
||||
|
||||
def scmRevisionForPath(self, path):
|
||||
xml = subprocess.check_output(["svn", "info", "--xml", path])
|
||||
root = ET.fromstring(xml)
|
||||
commit = root.find(".//entry/commit")
|
||||
return commit.get('revision', 0)
|
||||
|
||||
def update(self):
|
||||
print "SVN update of", self._path
|
||||
subprocess.call(["svn", "update", self._path])
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Template catalog - copy and modify for your site as required
|
||||
-->
|
||||
<PropertyList>
|
||||
|
||||
<!--
|
||||
catalogProps.addChild('version').value = '3.1.0'
|
||||
catalogProps.addChild('id').value = 'org.flightgear.default'
|
||||
catalogProps.addChild('license').value = 'GPL'
|
||||
catalogProps.addChild('url').value = "http://fgfs.goneabitbursar.com/pkg/3.1.0/default-catalog.xml"
|
||||
|
||||
catalogProps.addChild('description').value = "Aircraft developed and maintained by the FlightGear project"
|
||||
|
||||
de = catalogProps.addChild('de')
|
||||
# de.addChild('description').value = "<German translation of catalog description>"
|
||||
|
||||
fr = catalogProps.addChild('fr')
|
||||
-->
|
||||
|
||||
<version>3.4.*</version>
|
||||
<version>3.5.*</version>
|
||||
<version>3.6.*</version>
|
||||
|
||||
<id>org.myorganisation.hangar</id>
|
||||
<license>GPL</license>
|
||||
<url>http://some.stable.url.com/foo/bar/catalog.xml</url>
|
||||
|
||||
<description>A collection of interesting aircraft with some features
|
||||
</description>
|
||||
|
||||
<de>
|
||||
<description>Au Deutsch</description>
|
||||
</de>
|
||||
|
||||
<fr>
|
||||
<description>Francais</description>
|
||||
</fr>
|
||||
|
||||
<mirror>http://some.url/</mirror>
|
||||
<!-- <mirror>another mirror</mirror> -->
|
||||
|
||||
|
||||
<thumbnails>http://some.url/images</thumbnails>
|
||||
|
||||
<git-repository>git://some.git.repo/</git-repository>
|
||||
|
||||
<repository-prefix>Aircraft</repository-prefix>
|
||||
|
||||
</PropertyList>
|
||||
|
||||
|
||||
Submodule windows-3rd-party updated: 527969ffe1...790648cd69
Reference in New Issue
Block a user