Compare commits
281 Commits
release/pr
...
version/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2428ee5846 | ||
|
|
c579c1bf9d | ||
|
|
6f16e81aba | ||
|
|
418cf6820e | ||
|
|
1ac4ed1f57 | ||
|
|
0d1777684d | ||
|
|
b03d12313a | ||
|
|
13137727b0 | ||
|
|
7e30b2f87a | ||
|
|
6a356f7e18 | ||
|
|
b2743b92f3 | ||
|
|
f57a5ed4cb | ||
|
|
249f00dd32 | ||
|
|
f581b93d9b | ||
|
|
2a1b666a5e | ||
|
|
92864a4c1a | ||
|
|
03ef344ada | ||
|
|
b81e7868e7 | ||
|
|
a64e172c00 | ||
|
|
6927ffb67c | ||
|
|
6ae033aa68 | ||
|
|
d60b866718 | ||
|
|
57e20e046a | ||
|
|
914241cc79 | ||
|
|
6e61261a52 | ||
|
|
cd41e9713f | ||
|
|
78a51fb6e1 | ||
|
|
5a64d51e10 | ||
|
|
32738decf4 | ||
|
|
378b261aaa | ||
|
|
20f6511228 | ||
|
|
8f8b7b24c1 | ||
|
|
c9fc223310 | ||
|
|
067afcd2b3 | ||
|
|
e61ebfae25 | ||
|
|
bbceb8429c | ||
|
|
450ab705d2 | ||
|
|
e50b26e537 | ||
|
|
30f7151599 | ||
|
|
4a557f9ff8 | ||
|
|
58e822462a | ||
|
|
3ff1d47aa6 | ||
|
|
4106b73f36 | ||
|
|
0cd4679fbc | ||
|
|
f65a068fe4 | ||
|
|
7e5ea0e055 | ||
|
|
5c8b686cde | ||
|
|
92b7ab1b09 | ||
|
|
99026272a1 | ||
|
|
d930779381 | ||
|
|
141be1410a | ||
|
|
5b1b01bb0f | ||
|
|
0c36cc3eef | ||
|
|
3aacabdfd0 | ||
|
|
9d00aec7dd | ||
|
|
6f54db6d76 | ||
|
|
b11fae7f37 | ||
|
|
8823d89f42 | ||
|
|
c19096b0af | ||
|
|
d943076183 | ||
|
|
955fa86000 | ||
|
|
c67f750862 | ||
|
|
5d112a90d4 | ||
|
|
b75295f647 | ||
|
|
4ac12095a6 | ||
|
|
deeeddbfbb | ||
|
|
e0504be7cf | ||
|
|
3c0683185f | ||
|
|
a28832b029 | ||
|
|
2d119001c6 | ||
|
|
dec3202ba6 | ||
|
|
479a175587 | ||
|
|
f61ceb1293 | ||
|
|
d2cb130135 | ||
|
|
bd453e4a3e | ||
|
|
8b62b242a4 | ||
|
|
80f7a7f2d3 | ||
|
|
78de3e4243 | ||
|
|
565feadfa6 | ||
|
|
242c0f9172 | ||
|
|
651482a0df | ||
|
|
f0fff6d16e | ||
|
|
8d1e9abcc9 | ||
|
|
5944ad64d9 | ||
|
|
cf1afee705 | ||
|
|
548de8bd2d | ||
|
|
f390d16625 | ||
|
|
fbda7475f0 | ||
|
|
287380d98d | ||
|
|
355a88d0cd | ||
|
|
245ab83192 | ||
|
|
0c3bf73b01 | ||
|
|
689f73ef76 | ||
|
|
4bf8367d3c | ||
|
|
d4890af978 | ||
|
|
c2ef0ba2dc | ||
|
|
fae026da99 | ||
|
|
18889da1dc | ||
|
|
3977bab348 | ||
|
|
db21783c26 | ||
|
|
ede6d2fe85 | ||
|
|
20d4f3def3 | ||
|
|
853ca8b713 | ||
|
|
7e25d81d12 | ||
|
|
2b98575f39 | ||
|
|
1e5f4a4881 | ||
|
|
62f47ccd9d | ||
|
|
f16cdc0c80 | ||
|
|
d4b6eae8ee | ||
|
|
c7b112e8f4 | ||
|
|
3e739e8a0c | ||
|
|
9f542a9108 | ||
|
|
600d6cfb5f | ||
|
|
d001ca1263 | ||
|
|
e80520c9ac | ||
|
|
e70381a0b9 | ||
|
|
7db79e8414 | ||
|
|
0e24b325f4 | ||
|
|
9b72febb48 | ||
|
|
aed93a2267 | ||
|
|
1758cee3f3 | ||
|
|
c70b71d843 | ||
|
|
df541b96c8 | ||
|
|
09e7086560 | ||
|
|
a7162574b3 | ||
|
|
444d6be8ad | ||
|
|
0136cf6849 | ||
|
|
8f5a14dc93 | ||
|
|
0bde0fbce9 | ||
|
|
e3d55cf136 | ||
|
|
e57f5f761c | ||
|
|
c68585096d | ||
|
|
0856c9827f | ||
|
|
a54e3c43cb | ||
|
|
7c6278a7ff | ||
|
|
cb1819693d | ||
|
|
c09266504a | ||
|
|
3f2d05e183 | ||
|
|
ed043cd81c | ||
|
|
8ca2beb4cb | ||
|
|
bf9c4d93c0 | ||
|
|
85081d90e5 | ||
|
|
2eafcdbd90 | ||
|
|
cc7bc8fdbf | ||
|
|
dc11e32420 | ||
|
|
308f9bd6f9 | ||
|
|
aa74c27f0f | ||
|
|
ccc94446df | ||
|
|
39a3312d35 | ||
|
|
8c6b73ba36 | ||
|
|
80df632a34 | ||
|
|
020969d8a7 | ||
|
|
4cb8332ef4 | ||
|
|
742fe828b9 | ||
|
|
9291d90763 | ||
|
|
035b7f567b | ||
|
|
2855f5a3a3 | ||
|
|
4e343a57e8 | ||
|
|
223e0b9fdb | ||
|
|
4c73bad839 | ||
|
|
38277ea867 | ||
|
|
d586f9043c | ||
|
|
c6a4485de4 | ||
|
|
e9593dbe5b | ||
|
|
f8bd1181b1 | ||
|
|
2ddba10a14 | ||
|
|
841a58097b | ||
|
|
1514eaee73 | ||
|
|
d498ebbe61 | ||
|
|
74a0c9c4ab | ||
|
|
0db50a95a3 | ||
|
|
75c90bfb3f | ||
|
|
8e52a6a247 | ||
|
|
5b5d2865a6 | ||
|
|
6109e8717d | ||
|
|
4abdf82598 | ||
|
|
1ab162d4d6 | ||
|
|
c25db033d6 | ||
|
|
06619741c4 | ||
|
|
4f7be59b0d | ||
|
|
d54ef9f452 | ||
|
|
82931efe42 | ||
|
|
0e925e2b65 | ||
|
|
62a773ed04 | ||
|
|
b1f695a89c | ||
|
|
036899c620 | ||
|
|
636d71da45 | ||
|
|
b4ef60ce93 | ||
|
|
3eda43fa69 | ||
|
|
82feb39e2a | ||
|
|
15b395c983 | ||
|
|
65dbc2051a | ||
|
|
36ab364a91 | ||
|
|
9d1862e591 | ||
|
|
70ee8107b1 | ||
|
|
8639e504c3 | ||
|
|
4a114eb43d | ||
|
|
156a3e1cf1 | ||
|
|
1aa9ff4e84 | ||
|
|
2f9d983441 | ||
|
|
4c8174014e | ||
|
|
586daede43 | ||
|
|
0940dca867 | ||
|
|
783a8a8ee6 | ||
|
|
4c227f76e4 | ||
|
|
13cc7d5e50 | ||
|
|
67bfe88597 | ||
|
|
f98529dbce | ||
|
|
2e4f0171eb | ||
|
|
75cc4a410c | ||
|
|
fe39e97c2e | ||
|
|
5f94a6d623 | ||
|
|
102f797cc3 | ||
|
|
247ca7b113 | ||
|
|
0a81018df9 | ||
|
|
784a595e82 | ||
|
|
95d0692b0e | ||
|
|
af9a7e9bd2 | ||
|
|
a16f37e678 | ||
|
|
4a10d32c61 | ||
|
|
a2a2d6f354 | ||
|
|
866a234822 | ||
|
|
57dfbfe524 | ||
|
|
fe838ad8e8 | ||
|
|
ba53b4ce5f | ||
|
|
e5531723b8 | ||
|
|
9a1a5ce7a6 | ||
|
|
758488cd6d | ||
|
|
4ba10aafda | ||
|
|
9e8fc07ea1 | ||
|
|
9763440ef4 | ||
|
|
c78949fd4a | ||
|
|
7d21138771 | ||
|
|
0b5855fdee | ||
|
|
d627ec7360 | ||
|
|
56e9eb4b6a | ||
|
|
24e55d6b92 | ||
|
|
f625f7b5e5 | ||
|
|
2f97b62112 | ||
|
|
3378b289aa | ||
|
|
8fe9281692 | ||
|
|
5610f352af | ||
|
|
19e9e62ba6 | ||
|
|
75f1a35520 | ||
|
|
1e183ed9de | ||
|
|
8f53e02e26 | ||
|
|
19705077f5 | ||
|
|
5e82468203 | ||
|
|
40b0daec9f | ||
|
|
9019d3c49c | ||
|
|
530e41f1b0 | ||
|
|
c20802b84f | ||
|
|
b4b5f665c1 | ||
|
|
e5f6218be9 | ||
|
|
3c32c48955 | ||
|
|
8fc045b409 | ||
|
|
ecd1537a61 | ||
|
|
82fedc7362 | ||
|
|
958a9ac2ba | ||
|
|
9a02d6ecb7 | ||
|
|
20fffd5b2e | ||
|
|
bd19b4a2bd | ||
|
|
cf425684a6 | ||
|
|
ace2336cde | ||
|
|
abe9cb809a | ||
|
|
e72e6c5621 | ||
|
|
33693907c3 | ||
|
|
55933a7621 | ||
|
|
91fdda387d | ||
|
|
c2edd66b51 | ||
|
|
94ea65ec2e | ||
|
|
df6ee9a211 | ||
|
|
60c95026ec | ||
|
|
24fd57edd3 | ||
|
|
ecbee417b8 | ||
|
|
2c2c819a44 | ||
|
|
bac9b55f06 | ||
|
|
4e9ab5aa80 | ||
|
|
ecc8111986 | ||
|
|
5c289cb98c | ||
|
|
8302a21ef7 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -2,6 +2,7 @@ dist
|
||||
.DS_Store
|
||||
install
|
||||
3rdParty
|
||||
3rdParty.x64
|
||||
boost_1_44_0
|
||||
InstallConfig.iss
|
||||
Output
|
||||
@@ -9,5 +10,13 @@ output
|
||||
fgBuild
|
||||
sgBuild
|
||||
image
|
||||
build
|
||||
macflightgear
|
||||
fgdata
|
||||
src
|
||||
tmp
|
||||
Makefile
|
||||
CMakeFiles
|
||||
archivebuild
|
||||
osgbuild
|
||||
CMakeCache.txt
|
||||
*.pyc
|
||||
|
||||
20
.gitmodules
vendored
20
.gitmodules
vendored
@@ -1,12 +1,20 @@
|
||||
[submodule "simgear"]
|
||||
path = simgear
|
||||
url = git://gitorious.org/fg/simgear.git
|
||||
url = git://git.code.sf.net/p/flightgear/simgear
|
||||
branch = release/2016.4
|
||||
[submodule "flightgear"]
|
||||
path = flightgear
|
||||
url = git://gitorious.org/fg/flightgear.git
|
||||
url = git://git.code.sf.net/p/flightgear/flightgear
|
||||
branch = release/2016.4
|
||||
[submodule "fgrun"]
|
||||
path = fgrun
|
||||
url = git://gitorious.org/fg/fgrun.git
|
||||
[submodule "maclauncher"]
|
||||
path = maclauncher
|
||||
url = git://gitorious.org/fg/maclauncher.git
|
||||
url = git://git.code.sf.net/p/flightgear/fgrun
|
||||
branch = next
|
||||
[submodule "fgdata"]
|
||||
path = fgdata
|
||||
url = git://git.code.sf.net/p/flightgear/fgdata
|
||||
branch = release/2016.4
|
||||
[submodule "windows-3rd-party"]
|
||||
path = windows-3rd-party
|
||||
url = git://git.code.sf.net/p/flightgear/windows-3rd-party
|
||||
branch = master
|
||||
|
||||
168
CMakeLists.txt
Normal file
168
CMakeLists.txt
Normal file
@@ -0,0 +1,168 @@
|
||||
cmake_minimum_required (VERSION 2.8.0)
|
||||
|
||||
include (ExternalProject)
|
||||
|
||||
project(FlightGear-Meta)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install)
|
||||
message(STATUS "Default install dir set to ${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
set(SG_DEPS OSG)
|
||||
set(FG_DEPS SimGear)
|
||||
set(SG_CMAKE_ARGS "")
|
||||
set(FG_CMAKE_ARGS "")
|
||||
|
||||
|
||||
set(OSG_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(SG_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(FG_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(PLIB_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(RTI_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
|
||||
# OpenSceneGraph configuration
|
||||
#set(OSG_SOURCE http://www.openscenegraph.org/downloads/developer_releases/OpenSceneGraph-3.2.0.zip)
|
||||
set(OSG_SOURCE https://github.com/openscenegraph/osg.git)
|
||||
set(OSG_TAG OpenSceneGraph-3.2)
|
||||
|
||||
if (APPLE)
|
||||
# force disable Qt and Jasper
|
||||
set(OSG_CMAKE_ARGS
|
||||
-DOSG_USE_QT=0
|
||||
-DJASPER_LIBRARY=
|
||||
)
|
||||
# OSG with some patches applied for Mac
|
||||
set(OSG_SOURCE https://github.com/zakalawe/osg.git)
|
||||
set(OSG_TAG fgfs-osg-32)
|
||||
elseif(MSVC)
|
||||
set(OSG_MSVC "msvc")
|
||||
if (${MSVC_VERSION} EQUAL 1700)
|
||||
set(OSG_MSVC ${OSG_MSVC}110)
|
||||
elseif (${MSVC_VERSION} EQUAL 1600)
|
||||
set(OSG_MSVC ${OSG_MSVC}100)
|
||||
else (${MSVC_VERSION} EQUAL 1700)
|
||||
set(OSG_MSVC ${OSG_MSVC}90)
|
||||
endif (${MSVC_VERSION} EQUAL 1700)
|
||||
if (CMAKE_CL_64)
|
||||
set(OSG_MSVC ${OSG_MSVC}-64)
|
||||
set(RDPARTY_DIR 3rdParty.x64)
|
||||
list(APPEND FG_CMAKE_ARGS -DWITH_FGPANEL=OFF)
|
||||
else ()
|
||||
set(RDPARTY_DIR 3rdParty)
|
||||
endif (CMAKE_CL_64)
|
||||
|
||||
SET(OSG_CMAKE_ARGS
|
||||
-DOSG_USE_QT:BOOL=OFF
|
||||
-DBUILD_OSG_APPLICATIONS:BOOL=ON
|
||||
-DOSG_PLUGIN_SEARCH_INSTALL_DIR_FOR_PLUGINS:BOOL=OFF
|
||||
-DACTUAL_3RDPARTY_DIR:PATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}
|
||||
-DCMAKE_LIBRARY_PATH:STRING=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/lib
|
||||
-DCMAKE_INCLUDE_PATH:STRING=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include;${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include/freetype
|
||||
-DCURL_INCLUDE_DIR:PATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include
|
||||
-DTIFF_INCLUDE_DIR:PATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include
|
||||
-DGDAL_INCLUDE_DIR:PATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include
|
||||
-DGDAL_LIBRARY:FILEPATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/lib/gdal_i.lib
|
||||
-DTIFF_LIBRARY:FILEPATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/lib/libtiff.lib
|
||||
-DCURL_LIBRARY:FILEPATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/lib/libcurl_imp.lib
|
||||
-DFREETYPE_LIBRARY:FILEPATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/lib/freetype.lib
|
||||
-DFREETYPE_INCLUDE_DIR:PATH=${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include;${CMAKE_BINARY_DIR}/${RDPARTY_DIR}/include/freetype
|
||||
)
|
||||
|
||||
# for compatability with MSVC directory layout
|
||||
set(OSG_INSTALL_PREFIX ${OSG_INSTALL_PREFIX}/${OSG_MSVC}/OpenSceneGraph)
|
||||
set(FGRUN_INSTALL_PREFIX ${FGRUN_INSTALL_PREFIX}/${OSG_MSVC}/FGRun)
|
||||
set(FG_INSTALL_PREFIX ${FG_INSTALL_PREFIX}/${OSG_MSVC}/FlightGear)
|
||||
set(SG_INSTALL_PREFIX ${SG_INSTALL_PREFIX}/${OSG_MSVC}/SimGear)
|
||||
list(APPEND OSG_DEPS WinDeps)
|
||||
else()
|
||||
# normal OSG
|
||||
endif()
|
||||
|
||||
|
||||
ExternalProject_Add(OSG
|
||||
DEPENDS ${OSG_DEPS}
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
GIT_REPOSITORY ${OSG_SOURCE}
|
||||
GIT_TAG ${OSG_TAG}
|
||||
BINARY_DIR osgbuild
|
||||
CMAKE_ARGS ${OSG_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX=${OSG_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
# Because OSG install the libraries in lib64/ instead of lib/
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
ExternalProject_Add_Step(OSG after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink ${OSG_INSTALL_PREFIX}/lib64 ${OSG_INSTALL_PREFIX}/lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
||||
# FIXME install of OpenRTI is failing on Windows, files in PREFIX/share which
|
||||
# are ending up in C:/Program Files/OpenRTI
|
||||
if (FALSE)
|
||||
ExternalProject_Add(OpenRTI
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
DOWNLOAD_COMMAND GIT_REPOSITORY git://git.code.sf.net/p/openrti/OpenRTI
|
||||
BINARY_DIR rtibuild
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${RTI_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
list(APPEND SG_DEPS OpenRTI)
|
||||
list(APPEND SG_CMAKE_ARGS -DENABLE_RTI=1)
|
||||
list(APPEND FG_CMAKE_ARGS -DENABLE_RTI=1)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(SimGear
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
DEPENDS ${SG_DEPS}
|
||||
DOWNLOAD_COMMAND "" # no need to download
|
||||
UPDATE_COMMAND "" # or update.
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/simgear
|
||||
BINARY_DIR sgbuild
|
||||
CMAKE_ARGS ${SG_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX=${SG_INSTALL_PREFIX} -DCMAKE_PREFIX_PATH=${OSG_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
# because we download SimGear externally (via Git submodules),
|
||||
# the change-detection doesn't work. Ensure we always change
|
||||
# for changes
|
||||
ExternalProject_Add_Step(SimGear forcebuild
|
||||
ALWAYS 1
|
||||
COMMAND ${CMAKE_COMMAND} -E echo foo
|
||||
DEPENDERS build
|
||||
)
|
||||
|
||||
# on Windows, PLIB is in the 3rd-party dependencies zip
|
||||
if (NOT WIN32)
|
||||
set(PLIB_ARGS --disable-pw --disable-sl --disable-psl --disable-ssg --disable-ssgaux)
|
||||
|
||||
ExternalProject_Add(PLIB
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
URL http://plib.sourceforge.net/dist/plib-1.8.5.tar.gz
|
||||
URL_HASH MD5=47a6fbf63668c1eed631024038b2ea90
|
||||
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=${PLIB_INSTALL_PREFIX} ${PLIB_ARGS}
|
||||
BUILD_IN_SOURCE 1
|
||||
)
|
||||
|
||||
list(APPEND FG_DEPS PLIB)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(FlightGear
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
DEPENDS ${FG_DEPS}
|
||||
DOWNLOAD_COMMAND "" # no need to download
|
||||
UPDATE_COMMAND "" # or update.
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/flightgear
|
||||
BINARY_DIR fgbuild
|
||||
CMAKE_ARGS ${FG_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX=${FG_INSTALL_PREFIX} -DCMAKE_PREFIX_PATH=${OSG_INSTALL_PREFIX} -DADDITIONAL_LIBRARY_PATHS=${SG_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
# because we download FlightGear externally (via Git submodules),
|
||||
# the change-detection doesn't work. Ensure we always change
|
||||
# for changes
|
||||
ExternalProject_Add_Step(FlightGear forcebuild
|
||||
ALWAYS 1
|
||||
COMMAND ${CMAKE_COMMAND} -E echo foo
|
||||
DEPENDERS build
|
||||
)
|
||||
664
FlightGear.iss
664
FlightGear.iss
@@ -1,293 +1,371 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
;
|
||||
; This script creates an installable FlightGear package for Win32 using the
|
||||
; "Inno Setup" package builder. Inno Setup is free (but probably not open
|
||||
; source?.) The official web site for this package building software is:
|
||||
;
|
||||
; http://www.jrsoftware.org/isinfo.php
|
||||
;
|
||||
; Note: the files must appear in the X: drive.
|
||||
; You can do this with the command below:
|
||||
;
|
||||
; subst X: path_to_files
|
||||
;
|
||||
; For example:
|
||||
;
|
||||
; 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 10.0"
|
||||
#else
|
||||
#define VSInstallDir GetEnv("VSINSTALLDIR")
|
||||
#endif
|
||||
|
||||
#define VCInstallDir VSInstallDir + "\VC"
|
||||
#define OSGInstallDir "X:\install\msvc100\OpenSceneGraph"
|
||||
#define OSGPluginsDir OSGInstallDir + "\bin\osgPlugins-" + OSGVersion
|
||||
|
||||
#define OSG64InstallDir "X:\install\msvc100-64\OpenSceneGraph"
|
||||
#define OSG64PluginsDir OSG64InstallDir + "\bin\osgPlugins-" + OSGVersion
|
||||
|
||||
[Setup]
|
||||
AppId=FlightGear
|
||||
AppName=FlightGear
|
||||
AppPublisher=The FlightGear Team
|
||||
OutputBaseFilename=fgsetup-{#FGVersion}
|
||||
AppVerName=FlightGear v{#FGVersion}
|
||||
AppPublisherURL=http://www.flightgear.org
|
||||
AppSupportURL=http://www.flightgear.org
|
||||
AppUpdatesURL=http://www.flightgear.org
|
||||
DefaultDirName={pf}\FlightGear
|
||||
DefaultGroupName=FlightGear {#FGVersion}
|
||||
LicenseFile=X:\flightgear\COPYING
|
||||
Uninstallable=yes
|
||||
SetupIconFile=X:\flightgear\package\flightgear.ico
|
||||
VersionInfoVersion={#FGVersion}.0
|
||||
WizardImageFile=X:\flightgear\package\Win32-Inno\setupimg.bmp
|
||||
WizardImageStretch=No
|
||||
WizardSmallImageFile=X:\flightgear\package\Win32-Inno\setupsmall.bmp
|
||||
VersionInfoCompany=The FlightGear Team
|
||||
UninstallDisplayIcon=X:\flightgear\projects\VC90\flightgear.ico
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
ArchitecturesAllowed=x86 x64
|
||||
|
||||
[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)"
|
||||
Name: "force32"; Description: "Force 32bit install on 64bit system"; Check: Is64BitInstallMode
|
||||
|
||||
[Files]
|
||||
; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at)
|
||||
;Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\fgfs.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "X:\install\msvc100-64\FlightGear\bin\fgfs.exe"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
;Unconditional install
|
||||
Source: "X:\install\msvc100\FlightGear\bin\fgadmin.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\terrasync.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\js_demo.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\fgjs.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\fgpanel.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\GPSsmooth.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\UGsmooth.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\MIDGsmooth.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\metar.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\install\msvc100\FlightGear\bin\yasim.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion
|
||||
Source: "X:\3rdParty\bin\*.dll"; DestDir: "{app}\bin\Win32"
|
||||
|
||||
Source: "X:\install\msvc100\FGRun\bin\fgrun.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion ; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "X:\install\msvc100\FGRun\share\locale\*"; DestDir: "{app}\bin\Win32\locale"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
|
||||
Source: "X:\install\msvc100-64\FGRun\bin\fgrun.exe"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "X:\install\msvc100-64\FGRun\share\locale\*"; DestDir: "{app}\bin\Win64\locale"; Flags: ignoreversion recursesubdirs skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Source: "X:\3rdParty.x64\bin\*.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Source: "{#VCInstallDir}\redist\x86\Microsoft.VC100.CRT\*.dll"; DestDir: "{app}\bin\Win32"
|
||||
Source: "{#VCInstallDir}\redist\x64\Microsoft.VC100.CRT\*.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "X:\3rdParty\bin\vcredist_x86.exe"; DestDir: "{app}\bin\Win32"; Flags: skipifsourcedoesntexist
|
||||
Source: "X:\3rdParty.x64\bin\vcredist_x64.exe"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Source: "X:\3rdParty\bin\oalinst.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion skipifsourcedoesntexist
|
||||
|
||||
Source: "X:\data\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs skipifsourcedoesntexist
|
||||
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osg.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgDB.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgGA.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgParticle.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgText.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgUtil.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgViewer.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgSim.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgFX.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
|
||||
Source: "{#OSGInstallDir}\bin\ot12-OpenThreads.dll"; DestDir: "{app}\bin\Win32"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
|
||||
Source: "{#OSGPluginsDir}\osgdb_ac.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_osg.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_osga.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_3ds.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_mdl.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_jpeg.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_rgb.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_png.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_dds.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_txf.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_freetype.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osg.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osganimation.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgfx.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgmanipulator.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgparticle.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgshadow.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgsim.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgterrain.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgtext.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_serializers_osgvolume.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_deprecated_osg.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Source: "{#OSGPluginsDir}\osgdb_deprecated_osgparticle.dll"; DestDir: "{app}\bin\Win32\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osg.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgDB.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgGA.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgParticle.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgText.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgUtil.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgViewer.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgSim.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgFX.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Source: "{#OSG64InstallDir}\bin\ot12-OpenThreads.dll"; DestDir: "{app}\bin\Win64"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Source: "{#OSG64PluginsDir}\osgdb_ac.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_osg.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_osga.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_3ds.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_mdl.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_jpeg.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_rgb.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_png.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_dds.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_txf.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_freetype.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osg.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osganimation.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgfx.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgmanipulator.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgparticle.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgshadow.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgsim.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgterrain.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgtext.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_serializers_osgvolume.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_deprecated_osg.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
Source: "{#OSG64PluginsDir}\osgdb_deprecated_osgparticle.dll"; DestDir: "{app}\bin\Win64\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
[Dirs]
|
||||
; Make the user installable scenery directory
|
||||
Name: "{app}\scenery"; Permissions: everyone-modify
|
||||
Name: "{code:TerrasyncDir}"; Permissions: everyone-modify
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\FlightGear Launcher"; Filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Name: "{group}\FlightGear Launcher"; Filename: "{app}\bin\Win64\fgrun.exe"; WorkingDir: "{app}"; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
; Name: "{group}\FlightGear"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}";
|
||||
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: "{userdesktop}\FlightGear {#FGVersion}"; Filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}"; Tasks: desktopicon; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
Name: "{userdesktop}\FlightGear {#FGVersion}"; Filename: "{app}\bin\Win64\fgrun.exe"; WorkingDir: "{app}"; Tasks: desktopicon; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
Name: "{group}\Tools\Install & Uninstall Scenery"; Filename: "{app}\bin\Win32\fgadmin.exe"; WorkingDir: "{app}"
|
||||
Name: "{group}\Tools\TerraSync"; Filename: "{app}\bin\Win32\terrasync.exe"; Parameters: "-S -p 5505 -d ""{app}\terrasync"""; WorkingDir: "{app}"
|
||||
Name: "{group}\Tools\Uninstall FlightGear"; Filename: "{uninstallexe}"
|
||||
|
||||
Name: "{group}\Tools\js_demo"; Filename: "{app}\bin\Win32\js_demo.exe"
|
||||
Name: "{group}\Tools\fgjs"; Filename: "cmd"; Parameters: "/k fgjs.exe ""--fg-root={app}\data"""; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\GPSsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\GPSsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\UGsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\UGsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\MIDGsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\MIDGsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\metar"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\metar.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\yasim"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\yasim.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\fgpanel"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\fgpanel.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
|
||||
Name: "{group}\Tools\Explore Documentation Folder"; Filename: "{app}\data\Docs"
|
||||
|
||||
; For running flightgear directly
|
||||
; Name: "{userdesktop}\FlightGear v2.0.0"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
filename: "cmd.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "/C del msvc*.dll"; Check: FileExists(ExpandConstant('{app}\bin\Win32\vcredist_x86.exe'))
|
||||
filename: "cmd.exe"; WorkingDir: "{app}\bin\Win64"; Parameters: "/C del msvc*.dll"; Check: FileExists(ExpandConstant('{app}\bin\Win64\vcredist_x64.exe'))
|
||||
filename: "{app}\bin\Win32\vcredist_x86.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "/passive /norestart"; Description: "Installing MS Visual C++ runtime components"; Check: FileExists(ExpandConstant('{app}\bin\Win32\vcredist_x86.exe'))
|
||||
filename: "{app}\bin\Win64\vcredist_x64.exe"; WorkingDir: "{app}\bin\Win64"; Parameters: "/passive /norestart"; Description: "Installing MS Visual C++ runtime components"; Check: Is64BitInstallMode and not IsTaskSelected('force32') and FileExists(ExpandConstant('{app}\bin\Win64\vcredist_x64.exe'))
|
||||
filename: "{app}\bin\Win32\oalinst.exe"; WorkingDir: "{app}\bin\Win32"; Description: "Installing OpenAL"; Check: IsTaskSelected('insoal') and FileExists(ExpandConstant('{app}\bin\Win32\oalinst.exe'))
|
||||
|
||||
; Put installation directory into the fgrun.prefs
|
||||
filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--fg-exe={app}\bin\Win32\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3 --version={#FGVersion}"; Check: not Is64BitInstallMode or IsTaskSelected('force32')
|
||||
filename: "{app}\bin\Win64\fgrun.exe"; WorkingDir: "{app}\bin\Win64"; Parameters: "--silent ""--fg-exe={app}\bin\Win64\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3 --version={#FGVersion}"; Check: Is64BitInstallMode and not IsTaskSelected('force32')
|
||||
|
||||
; Put installation and source directories into the fgadmin.prefs
|
||||
filename: "{app}\bin\Win32\fgadmin.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--install-source={src}\..\Scenery"" ""--scenery-dest={app}\scenery"""
|
||||
|
||||
[Registry]
|
||||
Root: HKLM; Subkey: "Software\flightgear.org"; ValueType: string; ValueName: "TerrasyncDir"; ValueData: "{code:TerrasyncDir}"
|
||||
|
||||
[Code]
|
||||
var
|
||||
TerrasyncDirPage: TInputDirWizardPage;
|
||||
|
||||
procedure URLLabelOnClick(Sender: TObject);
|
||||
var
|
||||
ErrorCode: Integer;
|
||||
begin
|
||||
ShellExec('open', 'http://www.flightgear.org', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
|
||||
end;
|
||||
|
||||
procedure CreateURLLabel(ParentForm: TSetupForm; CancelButton: TNewButton);
|
||||
var
|
||||
URLLabel: TNewStaticText;
|
||||
begin
|
||||
URLLabel := TNewStaticText.Create(ParentForm);
|
||||
URLLabel.Caption := 'www.flightgear.org';
|
||||
URLLabel.Cursor := crHand;
|
||||
URLLabel.OnClick := @URLLabelOnClick;
|
||||
URLLabel.Parent := ParentForm;
|
||||
{ Alter Font *after* setting Parent so the correct defaults are inherited first }
|
||||
URLLabel.Font.Style := URLLabel.Font.Style + [fsUnderline];
|
||||
URLLabel.Font.Color := clBlue;
|
||||
URLLabel.Top := CancelButton.Top + CancelButton.Height - URLLabel.Height - 2;
|
||||
URLLabel.Left := ScaleX(20);
|
||||
end;
|
||||
|
||||
procedure InitializeWizard();
|
||||
begin
|
||||
TerrasyncDirPage := CreateInputDirPage(wpSelectDir,
|
||||
'Select Terrasync Directory', 'Where should scenery downloaded by Terrasync be put?',
|
||||
'Select the folder in which Terrasync would download additional scenery, then click Next.',
|
||||
False, 'Terrasync Folder');
|
||||
TerrasyncDirPage.Add('');
|
||||
|
||||
CreateURLLabel(WizardForm, WizardForm.CancelButton);
|
||||
end;
|
||||
|
||||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||||
begin
|
||||
if CurPageID = wpSelectDir then begin
|
||||
TerrasyncDirPage.Values[0] := GetPreviousData( 'TerrasyncDir', ExpandConstant('{reg:HKLM\Software\flightgear.org,TerrasyncDir|{app}\terrasync}') );
|
||||
end;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TerrasyncDir(Param: String): String;
|
||||
begin
|
||||
Result := TerrasyncDirPage.Values[0];
|
||||
end;
|
||||
|
||||
procedure RegisterPreviousData(PreviousDataKey: Integer);
|
||||
begin
|
||||
{ Store the settings so we can restore them next time }
|
||||
SetPreviousData(PreviousDataKey, 'TerrasyncDir', TerrasyncDirPage.Values[0]);
|
||||
end;
|
||||
|
||||
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
S := '';
|
||||
S := S + MemoDirInfo + NewLine + NewLine;
|
||||
S := S + 'Terrasync folder:' + NewLine;
|
||||
S := S + Space + TerrasyncDirPage.Values[0] + NewLine + NewLine;
|
||||
S := S + MemoGroupInfo + NewLine + NewLine;
|
||||
S := S + MemoTasksInfo + NewLine + NewLine;
|
||||
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
;
|
||||
; This script creates an installable FlightGear package for Win32 using the
|
||||
; "Inno Setup" package builder. Inno Setup is free (but probably not open
|
||||
; source?.) The official web site for this package building software is:
|
||||
;
|
||||
; http://www.jrsoftware.org/isinfo.php
|
||||
;
|
||||
; Note: the files must appear in the X: drive.
|
||||
; You can do this with the command below:
|
||||
;
|
||||
; subst X: path_to_files
|
||||
;
|
||||
; For example:
|
||||
;
|
||||
; 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
|
||||
|
||||
#define InstallDir64 "X:\install\msvc140-64"
|
||||
#define OSG64InstallDir InstallDir64 + "\OpenSceneGraph"
|
||||
#define OSG64PluginsDir OSG64InstallDir + "\bin\osgPlugins-" + OSGVersion
|
||||
|
||||
#define ThirdPartyDir "X:\windows-3rd-party\msvc140"
|
||||
|
||||
; we copy everything in install/<arch>/bin except these, which aren't
|
||||
; useful to the end-user to ship
|
||||
#define ExcludedBinaries "*smooth.exe,metar.exe,js_demo.exe"
|
||||
|
||||
[Setup]
|
||||
AppId=FlightGear
|
||||
AppName=FlightGear
|
||||
AppPublisher=The FlightGear Team
|
||||
OutputBaseFilename=FlightGear-{#FGVersion}{#FGDetails}
|
||||
AppVerName=FlightGear v{#FGVersion}
|
||||
AppPublisherURL=http://www.flightgear.org
|
||||
AppSupportURL=http://www.flightgear.org
|
||||
AppUpdatesURL=http://www.flightgear.org
|
||||
DefaultDirName={pf}\FlightGear {#FGVersion}
|
||||
UsePreviousAppDir=no
|
||||
DefaultGroupName=FlightGear {#FGVersion}
|
||||
UsePreviousGroup=no
|
||||
LicenseFile=X:\flightgear\COPYING
|
||||
Uninstallable=yes
|
||||
SetupIconFile=X:\flightgear\package\flightgear.ico
|
||||
VersionInfoVersion={#FGVersion}.0
|
||||
InfoBeforeFile=X:\flightgear\package\windows\infobefore.txt
|
||||
WizardImageFile=X:\flightgear\package\windows\setupimg.bmp
|
||||
WizardImageStretch=No
|
||||
WizardSmallImageFile=X:\flightgear\package\windows\setupsmall.bmp
|
||||
VersionInfoCompany=The FlightGear Team
|
||||
UninstallDisplayIcon={app}\bin\fgfs.exe
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
ArchitecturesAllowed=x86 x64
|
||||
|
||||
; Sign tool must be defined in the Inno Setup GUI, to avoid
|
||||
; exposing the certificate password
|
||||
; 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)
|
||||
;Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
; 32 bits install
|
||||
|
||||
Source: "{#InstallDir32}\bin\*.*"; DestDir: "{app}\bin"; Excludes: "{#ExcludedBinaries}"; 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
|
||||
|
||||
; 64 bits install
|
||||
Source: "{#InstallDir64}\bin\*.*"; DestDir: "{app}\bin"; Excludes: "{#ExcludedBinaries}"; 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: "{#ThirdPartyDir}\..\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion skipifsourcedoesntexist
|
||||
|
||||
; Include the base package
|
||||
#if IncludeData == "TRUE"
|
||||
Source: "X:\fgdata\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs skipifsourcedoesntexist
|
||||
#endif
|
||||
|
||||
; 32 bits install
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osg.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgDB.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgGA.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgParticle.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgText.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgUtil.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgViewer.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgSim.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\osg{#OSGSoNumber}-osgFX.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGInstallDir}\bin\ot{#OTSoNumber}-OpenThreads.dll"; DestDir: "{app}\bin"; Check: not Is64BitInstallMode
|
||||
|
||||
Source: "{#OSGPluginsDir}\osgdb_ac.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_osga.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_3ds.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_mdl.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_jpeg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_rgb.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_png.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_dds.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_txf.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_tiff.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
Source: "{#OSGPluginsDir}\osgdb_freetype.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osganimation.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgfx.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgmanipulator.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgparticle.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgshadow.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgsim.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgterrain.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgtext.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_serializers_osgvolume.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_deprecated_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
;Source: "{#OSGPluginsDir}\osgdb_deprecated_osgparticle.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Check: not Is64BitInstallMode
|
||||
|
||||
; 64 bits install
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osg.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgDB.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgGA.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgParticle.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgText.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgUtil.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgViewer.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgSim.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\osg{#OSGSoNumber}-osgFX.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64InstallDir}\bin\ot{#OTSoNumber}-OpenThreads.dll"; DestDir: "{app}\bin"; Check: Is64BitInstallMode
|
||||
|
||||
Source: "{#OSG64PluginsDir}\osgdb_ac.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_osga.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_3ds.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_mdl.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_jpeg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_rgb.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_png.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_dds.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_txf.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_tiff.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
Source: "{#OSG64PluginsDir}\osgdb_freetype.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osganimation.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgfx.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgmanipulator.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgparticle.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgshadow.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgsim.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgterrain.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgtext.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_serializers_osgvolume.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_deprecated_osg.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
;Source: "{#OSG64PluginsDir}\osgdb_deprecated_osgparticle.dll"; DestDir: "{app}\bin\osgPlugins-{#OSGVersion}"; Flags: skipifsourcedoesntexist; Check: Is64BitInstallMode
|
||||
|
||||
[Dirs]
|
||||
; Make the user installable scenery directory
|
||||
Name: "{userdocs}\FlightGear\Aircraft"; Permissions: everyone-modify; Check: not DirExists(ExpandConstant('{userdocs}\FlightGear\Aircraft'))
|
||||
Name: "{userdocs}\FlightGear\TerraSync"; Permissions: everyone-modify; Check: not DirExists(ExpandConstant('{userdocs}\FlightGear\TerraSync'))
|
||||
Name: "{userdocs}\FlightGear\Custom Scenery"; Permissions: everyone-modify; Check: not DirExists(ExpandConstant('{userdocs}\FlightGear\Custom Scenery'))
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\FlightGear {#FGVersion}"; Filename: "{app}\bin\fgfs.exe"; Parameters: "--launcher"; WorkingDir: "{app}\bin"; Tasks: desktopicon;
|
||||
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\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"
|
||||
Name: "{group}\Tools\fgpanel"; Filename: "cmd"; Parameters: "/k ""{app}\bin\fgpanel.exe"" -h"; WorkingDir: "{app}\bin"
|
||||
Name: "{group}\Tools\FGCom"; Filename: "{app}\bin\fgcom.exe"; WorkingDir: "{app}\bin"
|
||||
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'))
|
||||
|
||||
[Code]
|
||||
const
|
||||
NET_FW_SCOPE_ALL = 0;
|
||||
NET_FW_IP_VERSION_ANY = 2;
|
||||
NET_FW_ACTION_ALLOW = 1;
|
||||
NET_FW_RULE_DIR_ALL = 0;
|
||||
NET_FW_RULE_DIR_IN = 1;
|
||||
NET_FW_RULE_DIR_OUT = 2;
|
||||
NET_FW_IP_PROTOCOL_ALL = 0;
|
||||
NET_FW_IP_PROTOCOL_TCP = 6;
|
||||
NET_FW_IP_PROTOCOL_UDP = 17;
|
||||
NET_FW_PROFILE2_DOMAIN = 1;
|
||||
NET_FW_PROFILE2_PRIVATE = 2;
|
||||
NET_FW_PROFILE2_PUBLIC = 4;
|
||||
|
||||
procedure URLLabelOnClick(Sender: TObject);
|
||||
var
|
||||
ErrorCode: Integer;
|
||||
begin
|
||||
ShellExec('open', 'http://www.flightgear.org', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
|
||||
end;
|
||||
|
||||
procedure CreateURLLabel(ParentForm: TSetupForm; CancelButton: TNewButton);
|
||||
var
|
||||
URLLabel: TNewStaticText;
|
||||
begin
|
||||
URLLabel := TNewStaticText.Create(ParentForm);
|
||||
URLLabel.Caption := 'www.flightgear.org';
|
||||
URLLabel.Cursor := crHand;
|
||||
URLLabel.OnClick := @URLLabelOnClick;
|
||||
URLLabel.Parent := ParentForm;
|
||||
{ Alter Font *after* setting Parent so the correct defaults are inherited first }
|
||||
URLLabel.Font.Style := URLLabel.Font.Style + [fsUnderline];
|
||||
URLLabel.Font.Color := clBlue;
|
||||
URLLabel.Top := CancelButton.Top + CancelButton.Height - URLLabel.Height - 2;
|
||||
URLLabel.Left := ScaleX(20);
|
||||
end;
|
||||
|
||||
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
S := '';
|
||||
S := S + MemoDirInfo + NewLine + NewLine;
|
||||
S := S + MemoGroupInfo + NewLine + NewLine;
|
||||
S := S + MemoTasksInfo + NewLine + NewLine;
|
||||
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
procedure AddBasicFirewallException(AppName, FileName: String);
|
||||
var
|
||||
FirewallObject: variant;
|
||||
RuleObject: variant;
|
||||
begin
|
||||
try
|
||||
FirewallObject := CreateOleObject('HNetCfg.FwMgr');
|
||||
RuleObject := CreateOleObject('HNetCfg.FwAuthorizedApplication');
|
||||
RuleObject.ProcessImageFileName := FileName;
|
||||
RuleObject.Name := AppName;
|
||||
RuleObject.Scope := NET_FW_SCOPE_ALL;
|
||||
RuleObject.IpVersion := NET_FW_IP_VERSION_ANY;
|
||||
RuleObject.Enabled := true;
|
||||
FirewallObject.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(RuleObject);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddAdvancedFirewallException(AppName, AppDescription, FileName: String; Protocol: Integer; LocalPorts, RemotePorts: String; Direction: Integer);
|
||||
var
|
||||
FirewallObject: variant;
|
||||
RuleObject: variant;
|
||||
begin
|
||||
try
|
||||
FirewallObject := CreateOleObject('HNetCfg.FwPolicy2');
|
||||
RuleObject := CreateOleObject('HNetCfg.FWRule');
|
||||
RuleObject.Name := AppName;
|
||||
RuleObject.Description := AppDescription;
|
||||
RuleObject.ApplicationName := FileName;
|
||||
if (Protocol <> NET_FW_IP_PROTOCOL_ALL) then
|
||||
RuleObject.Protocol := Protocol;
|
||||
if (LocalPorts <> '') then
|
||||
RuleObject.LocalPorts := LocalPorts;
|
||||
if (RemotePorts <> '') then
|
||||
RuleObject.RemotePorts := RemotePorts;
|
||||
if (Direction <> NET_FW_RULE_DIR_ALL) then
|
||||
RuleObject.Direction := Direction;
|
||||
RuleObject.Enabled := true;
|
||||
RuleObject.Grouping := 'FlightGear';
|
||||
RuleObject.Profiles := NET_FW_PROFILE2_DOMAIN + NET_FW_PROFILE2_PRIVATE + NET_FW_PROFILE2_PUBLIC;
|
||||
RuleObject.Action := NET_FW_ACTION_ALLOW;
|
||||
RuleObject.RemoteAddresses := '*';
|
||||
FirewallObject.Rules.Add(RuleObject);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RemoveFirewallException(AppName, FileName: String);
|
||||
var
|
||||
FirewallObject: variant;
|
||||
Version: TWindowsVersion;
|
||||
begin
|
||||
GetWindowsVersionEx(Version);
|
||||
try
|
||||
if (Version.Major >= 6) then
|
||||
begin
|
||||
FirewallObject := CreateOleObject('HNetCfg.FwPolicy2');
|
||||
FirewallObject.Rules.Remove(AppName);
|
||||
end
|
||||
else if (Version.Major = 5) and (((Version.Minor = 1) and (Version.ServicePackMajor >= 2)) or ((Version.Minor = 2) and (Version.ServicePackMajor >= 1))) then
|
||||
begin
|
||||
FirewallObject := CreateOleObject('HNetCfg.FwMgr');
|
||||
FirewallObject.LocalPolicy.CurrentProfile.AuthorizedApplications.Remove(FileName);
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
Version: TWindowsVersion;
|
||||
begin
|
||||
if CurStep = ssPostInstall then
|
||||
begin
|
||||
GetWindowsVersionEx(Version);
|
||||
if (Version.Major >= 6) then
|
||||
begin
|
||||
{ IN and OUT rules must be specified separately, otherwise the firewall will create only the IN rule }
|
||||
AddAdvancedFirewallException('FlightGear', 'Allows FlightGear to send and receive data over the multiplayer network and to get METARs.', ExpandConstant('{app}') + '\bin\fgfs.exe', NET_FW_IP_PROTOCOL_ALL, '', '', NET_FW_RULE_DIR_IN);
|
||||
AddAdvancedFirewallException('FlightGear', 'Allows FlightGear to send and receive data over the multiplayer network and to get METARs.', ExpandConstant('{app}') + '\bin\fgfs.exe', NET_FW_IP_PROTOCOL_ALL, '', '', NET_FW_RULE_DIR_OUT);
|
||||
AddAdvancedFirewallException('FlightGear FGCom', 'Allows FGCom to establish a connection to FlightGear and the VoIP server for voice ATC communication.', ExpandConstant('{app}') + '\bin\fgcom.exe', NET_FW_IP_PROTOCOL_ALL, '', '', NET_FW_RULE_DIR_IN);
|
||||
AddAdvancedFirewallException('FlightGear FGCom', 'Allows FGCom to establish a connection to FlightGear and the VoIP server for voice ATC communication.', ExpandConstant('{app}') + '\bin\fgcom.exe', NET_FW_IP_PROTOCOL_ALL, '', '', NET_FW_RULE_DIR_OUT);
|
||||
end
|
||||
else if (Version.Major = 5) and (((Version.Minor = 1) and (Version.ServicePackMajor >= 2)) or ((Version.Minor = 2) and (Version.ServicePackMajor >= 1))) then
|
||||
begin
|
||||
{ The Windows XP/Server 2003 firewall does not block outgoing connections at all, so only listening processes should be added }
|
||||
AddBasicFirewallException('FlightGear', ExpandConstant('{app}') + '\bin\fgfs.exe');
|
||||
AddBasicFirewallException('FlightGear FGCom', ExpandConstant('{app}') + '\bin\fgcom.exe');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
begin
|
||||
if CurUninstallStep = usPostUninstall then
|
||||
begin
|
||||
RemoveFirewallException('FlightGear', ExpandConstant('{app}') + '\bin\fgfs.exe');
|
||||
RemoveFirewallException('FlightGear FGCom', ExpandConstant('{app}') + '\bin\fgcom.exe');
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>FlightGear</string>
|
||||
<string>fgfs</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.flightgear.FlightGear</string>
|
||||
<key>CFBundleVersion</key>
|
||||
@@ -21,13 +21,20 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string><%= fgVersion %></string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.6.0</string>
|
||||
<string>10.7.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>©1996-<%= fgCurrentYear%>, The FlightGear Project</string>
|
||||
|
||||
<!-- when launched via LaunchServices, run the launcher GUI -->
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>FG_LAUNCHER</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
- .git
|
||||
- *.xcf
|
||||
- *.tex
|
||||
|
||||
+ /fgdata/Aircraft/Generic
|
||||
+ /fgdata/Aircraft/Instruments
|
||||
+ /fgdata/Aircraft/Instruments-3d
|
||||
|
||||
+ /fgdata/Aircraft/UIUC
|
||||
+ /fgdata/Aircraft/c172p
|
||||
+ /fgdata/Aircraft/777
|
||||
+ /fgdata/Aircraft/777-200
|
||||
+ /fgdata/Aircraft/b1900d
|
||||
+ /fgdata/Aircraft/ufo
|
||||
+ /fgdata/Aircraft/CitationX
|
||||
+ /fgdata/Aircraft/ZLT-NT
|
||||
+ /fgdata/Aircraft/dhc2
|
||||
+ /fgdata/Aircraft/Cub
|
||||
+ /fgdata/Aircraft/sopwithCamel
|
||||
+ /fgdata/Aircraft/f-14b
|
||||
+ /fgdata/Aircraft/ASK13
|
||||
+ /fgdata/Aircraft/bo105
|
||||
+ /fgdata/Aircraft/Dragonfly
|
||||
+ /fgdata/Aircraft/SenecaII
|
||||
+ /fgdata/Aircraft/A6M2
|
||||
|
||||
- /fgdata/Aircraft/*
|
||||
|
||||
- /fgdata/Textures.high/*.new
|
||||
- /fgdata/Textures.high/*.orig
|
||||
- /fgdata/Textures.high/*.save
|
||||
- /fgdata/Textures/Unused
|
||||
- /fgdata/Textures/*.orig
|
||||
- /fgdata/Docs/source
|
||||
- /fgdata/Models/Airspace
|
||||
- /fgdata/Models/MNUAV
|
||||
|
||||
|
||||
@@ -5,20 +5,21 @@ if [ "$WORKSPACE" == "" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=`cat flightgear/version`
|
||||
|
||||
#####################################################################################
|
||||
# remove old and create fresh build directories
|
||||
rm -rf sgBuild
|
||||
rm -rf fgBuild
|
||||
cd $WORKSPACE
|
||||
mkdir -p sgBuild
|
||||
mkdir -p fgBuild
|
||||
mkdir -p output
|
||||
rm -rf output/*
|
||||
rm -rf $WORKSPACE/dist/include/simgear $WORKSPACE/dist/libSim* $WORKSPACE/dist/libsg*.a
|
||||
rm -rf dist/*
|
||||
|
||||
#####################################################################################
|
||||
echo "Starting on SimGear"
|
||||
cd sgBuild
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DSIMGEAR_SHARED:BOOL="ON" ../simgear
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DENABLE_DNS:BOOL="ON" -DSIMGEAR_SHARED:BOOL="ON" ../simgear
|
||||
|
||||
# compile
|
||||
make
|
||||
@@ -53,3 +54,10 @@ make install
|
||||
make package_source
|
||||
cp flightgear-*.tar.bz2 ../output/.
|
||||
|
||||
#####################################################################################
|
||||
|
||||
echo "Assembling base package"
|
||||
cd $WORKSPACE
|
||||
|
||||
tar cjf output/FlightGear-$VERSION-data.tar.bz2 fgdata/
|
||||
|
||||
0
build_release_mac.sh
Executable file
0
build_release_mac.sh
Executable file
128
build_release_windows.bat
Executable file
128
build_release_windows.bat
Executable file
@@ -0,0 +1,128 @@
|
||||
|
||||
IF NOT DEFINED WORKSPACE SET WORKSPACE=%~dp0
|
||||
|
||||
REM following are for testing the script locally
|
||||
REM SET PATH=%PATH%;%ProgramFiles%\CMake\bin;%ProgramFiles(x86)%\"Inno Setup 5"\
|
||||
REM SET QT5SDK32=C:\Qt\5.6\msvc2015
|
||||
REM SET QT5SDK64=C:\Qt\5.6\msvc2015_64
|
||||
REM SET IS_NIGHTLY_BUILD=1
|
||||
|
||||
SET OSG32=%WORKSPACE%\install\msvc140\OpenSceneGraph
|
||||
SET OSG64=%WORKSPACE%\install\msvc140-64\OpenSceneGraph
|
||||
|
||||
REM 32bits
|
||||
md build-sg32
|
||||
md build-fg32
|
||||
cd build-sg32
|
||||
cmake ..\simgear -G "Visual Studio 14" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%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
|
||||
|
||||
cd ..\build-fg32
|
||||
cmake ..\flightgear -G "Visual Studio 14" ^
|
||||
-DMSVC_3RDPARTY_ROOT=%WORKSPACE%/windows-3rd-party/msvc140 ^
|
||||
-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 ..
|
||||
|
||||
REM 64 bits
|
||||
md build-sg64
|
||||
md build-fg64
|
||||
|
||||
cd build-sg64
|
||||
cmake ..\SimGear -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
|
||||
|
||||
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 ..
|
||||
|
||||
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
|
||||
|
||||
REM build setup
|
||||
ECHO Packaging root is %WORKSPACE%
|
||||
|
||||
subst X: /D
|
||||
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
|
||||
|
||||
REM indirect way to get command output into an environment variable
|
||||
set PATH=%OSG32%\bin;%PATH%
|
||||
osgversion --so-number > %TEMP%\osg-so-number.txt
|
||||
osgversion --version-number > %TEMP%\osg-version.txt
|
||||
osgversion --openthreads-soversion-number > %TEMP%\openthreads-so-number.txt
|
||||
|
||||
SET /P FLIGHTGEAR_VERSION=<flightgear\version
|
||||
SET /P OSG_VERSION=<%TEMP%\osg-version.txt
|
||||
SET /P OSG_SO_NUMBER=<%TEMP%\osg-so-number.txt
|
||||
SET /P OT_SO_NUMBER=<%TEMP%\openthreads-so-number.txt
|
||||
|
||||
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
|
||||
|
||||
REM FlightGear nightly: without fgdata, output filename would be "FlightGear-x.x.x-nightly.exe"
|
||||
CALL :writeBaseConfig
|
||||
CALL :writeNightlyDietConfig
|
||||
iscc FlightGear.iss
|
||||
) ELSE (
|
||||
REM FlightGear release: with fgdata, output filename would be "FlightGear-x.x.x.exe"
|
||||
CALL :writeBaseConfig
|
||||
CALL :writeReleaseConfig
|
||||
iscc FlightGear.iss
|
||||
)
|
||||
GOTO End
|
||||
|
||||
:writeBaseConfig
|
||||
ECHO #define FGVersion "%FLIGHTGEAR_VERSION%" > InstallConfig.iss
|
||||
ECHO #define OSGVersion "%OSG_VERSION%" >> InstallConfig.iss
|
||||
ECHO #define OSGSoNumber "%OSG_SO_NUMBER%" >> InstallConfig.iss
|
||||
ECHO #define OTSoNumber "%OT_SO_NUMBER%" >> InstallConfig.iss
|
||||
GOTO End
|
||||
|
||||
:writeReleaseConfig
|
||||
CALL :writeBaseConfig
|
||||
ECHO #define FGDetails "" >> InstallConfig.iss
|
||||
ECHO #define IncludeData "TRUE" >> InstallConfig.iss
|
||||
GOTO End
|
||||
|
||||
:writeNightlyFullConfig
|
||||
CALL :writeBaseConfig
|
||||
ECHO #define FGDetails "-nightly-full" >> InstallConfig.iss
|
||||
ECHO #define IncludeData "TRUE" >> InstallConfig.iss
|
||||
GOTO End
|
||||
|
||||
:writeNightlyDietConfig
|
||||
CALL :writeBaseConfig
|
||||
ECHO #define FGDetails "-nightly" >> InstallConfig.iss
|
||||
ECHO #define IncludeData "FALSE" >> InstallConfig.iss
|
||||
GOTO End
|
||||
|
||||
:End
|
||||
25
catalog/fgaddon-catalog/catalog.config.xml
Normal file
25
catalog/fgaddon-catalog/catalog.config.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Template catalog - copy and modify for your site as required-->
|
||||
<PropertyList>
|
||||
<local-output>/home/curt/Projects/FlightGear/ftp/Aircraft</local-output>
|
||||
<download-url n="0">http://mirrors.ibiblio.org/flightgear/ftp/Aircraft/</download-url>
|
||||
<thumbnail-url n="0">http://mirrors.ibiblio.org/flightgear/ftp/Aircraft/thumbnails</thumbnail-url>
|
||||
<scm>
|
||||
<type>svn</type>
|
||||
<path>/home/curt/Projects/FlightGear/flightgear-fgaddon/Aircraft</path>
|
||||
<skip>NTPS</skip>
|
||||
<skip>c172</skip>
|
||||
<skip>tu134</skip>
|
||||
</scm>
|
||||
<!-- <scm>
|
||||
<type>git</type>
|
||||
<update type="bool">false</update>
|
||||
<path>/Users/jmt/FGFS/fgdata</path>
|
||||
<url>git://git.code.sf.net/p/flightgear/fgdata</url>
|
||||
</scm> -->
|
||||
<upload n="0">
|
||||
<enabled type="bool">true</enabled>
|
||||
<type>rsync-ssh</type>
|
||||
<remote>fgfs:/home/fgfs/fgfs.goneabitbursar.com/official</remote>
|
||||
</upload>
|
||||
</PropertyList>
|
||||
516
catalog/fgaddon-catalog/md5sum.xml
Normal file
516
catalog/fgaddon-catalog/md5sum.xml
Normal file
@@ -0,0 +1,516 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<PropertyList>
|
||||
<aircraft_14bis>8a4ea48a3bb83b608386f942a85100c9</aircraft_14bis>
|
||||
<aircraft_21>057bfdb3c3fcfba3f8d31723a77df277</aircraft_21>
|
||||
<aircraft_707>088f6c3850d9c3f8e94ced2bfc2a65db</aircraft_707>
|
||||
<aircraft_717>abc393890f7ab49f32c6a2adc01b7823</aircraft_717>
|
||||
<aircraft_727-230>8e93ee83c42f77db9881f9ca0f00cf8b</aircraft_727-230>
|
||||
<aircraft_737-100>45fc009e9323de75e477b2548c79cb9a</aircraft_737-100>
|
||||
<aircraft_737-200>3fb8820c373e78bcd52981293e2d46e8</aircraft_737-200>
|
||||
<aircraft_737-300>c974d9b2e7c5feba195563433a4c5bc2</aircraft_737-300>
|
||||
<aircraft_737NG>dd9ab7cb3fb27a4acfc7b634fa9ec396</aircraft_737NG>
|
||||
<aircraft_747>5779ec5bdab4e9405d0db447c5a73df4</aircraft_747>
|
||||
<aircraft_747-200>e3565e459436a5e4dcdd260a095c28b2</aircraft_747-200>
|
||||
<aircraft_747-400>ce6c904cb23df6337ed6bdc1dcf6d68e</aircraft_747-400>
|
||||
<aircraft_747-8i>92161d0ef86048c0c859241abd64ffcd</aircraft_747-8i>
|
||||
<aircraft_757-200>9f5841317f4ed65fc815517c6770affd</aircraft_757-200>
|
||||
<aircraft_767-300>89c1b762b8b58fee4772a94d3c9b81d8</aircraft_767-300>
|
||||
<aircraft_777>693bf6470439f876edced4bd558b69a1</aircraft_777>
|
||||
<aircraft_787-8>f450b755c5bad640d8c2ef7312b1a6fb</aircraft_787-8>
|
||||
<aircraft_A-10>4aaca65794466d8cbf8e9ab29ef1b47b</aircraft_A-10>
|
||||
<aircraft_A-26-Invader>c57f1d877e851f2164f292997508dd36</aircraft_A-26-Invader>
|
||||
<aircraft_A-6E>86b52be36911fd0ee5d0b93d4b70a087</aircraft_A-6E>
|
||||
<aircraft_A24-Viking>904f23999e33d323d3f7a09c1807b71a</aircraft_A24-Viking>
|
||||
<aircraft_A300>3ae04898384a6531fa2edac2fcd508e9</aircraft_A300>
|
||||
<aircraft_A320-family>c9ec3df5ce80cbbbec9e39a849877ceb</aircraft_A320-family>
|
||||
<aircraft_A340-600>f015a7d2c8bde1224298261ae34e04c2</aircraft_A340-600>
|
||||
<aircraft_A380>4951432b9d39c142e891da3209e3ad32</aircraft_A380>
|
||||
<aircraft_a4>f175e90ccf2c3ae5118cf6eb1a43867e</aircraft_a4>
|
||||
<aircraft_A6M2>dfb5b7f4f7233d854dca45ae4521e080</aircraft_A6M2>
|
||||
<aircraft_Aermacchi-MB-339>f6757f3a4f78364c0439fd7d488c4330</aircraft_Aermacchi-MB-339>
|
||||
<aircraft_Aero-Commander>021be8bd26c7aa03093e5e356d8c7ef2</aircraft_Aero-Commander>
|
||||
<aircraft_Aerocar>89c4f1663f6b65ca1f70184dd8886f8b</aircraft_Aerocar>
|
||||
<aircraft_Aerostar-700>9049ec76bddd80abff57a837313771d8</aircraft_Aerostar-700>
|
||||
<aircraft_AG-14>4f9c9c24e662036de1cd85ed528c3d4e</aircraft_AG-14>
|
||||
<aircraft_Aichi-D3A>766eb03f38f36190de94422b5481ce4b</aircraft_Aichi-D3A>
|
||||
<aircraft_Aichi-M6A>14219343b589d8610da96f7a8ec16cdc</aircraft_Aichi-M6A>
|
||||
<aircraft_Airco-DH2>67689844de14068b7e95e675c0da6c17</aircraft_Airco-DH2>
|
||||
<aircraft_AirCrane>44fd70dc27b3d36bbde5766ac528d095</aircraft_AirCrane>
|
||||
<aircraft_Airspeed-Horsa>dae16af174310b492c4412e0c77593e8</aircraft_Airspeed-Horsa>
|
||||
<aircraft_airwaveXtreme150>64c7f53c6dac1b4da3813661f7455faf</aircraft_airwaveXtreme150>
|
||||
<aircraft_Albatros-BII>7ccb293d5808ca0b9c48271a6398de94</aircraft_Albatros-BII>
|
||||
<aircraft_Albatross>61af35090bbc722076353d1496c2d82f</aircraft_Albatross>
|
||||
<aircraft_Allegro-2000>edae78dee86c3c0cb741bc4ea8793162</aircraft_Allegro-2000>
|
||||
<aircraft_Alouette-II>94d5008f7bbfb65a56cff0694983d8ff</aircraft_Alouette-II>
|
||||
<aircraft_Alouette-III>c267be9f90def2460ff53649c6fee2f0</aircraft_Alouette-III>
|
||||
<aircraft_Alphajet>3fd4701f2363c41de0374c4703b88e83</aircraft_Alphajet>
|
||||
<aircraft_AN-225>87a1ad2288b56c71559549d55b93cccd</aircraft_AN-225>
|
||||
<aircraft_an2>37ccf863b017f0b773885619a671f8f7</aircraft_an2>
|
||||
<aircraft_an24b>3e26ca3bf5296630eebbcd82859d5ac4</aircraft_an24b>
|
||||
<aircraft_ANT-20>add26dd267eca688d4a88b672749a155</aircraft_ANT-20>
|
||||
<aircraft_Antoinette>75e69854bf9d09d16cbd5147926ba7fd</aircraft_Antoinette>
|
||||
<aircraft_Antonov-An-12>457f71d5be8ec8c3e42c6919b226b549</aircraft_Antonov-An-12>
|
||||
<aircraft_Antonov-An-22>4a27ba4bb53f82bf2a4b325cd3405a89</aircraft_Antonov-An-22>
|
||||
<aircraft_apache>b7e3e73c98d17006e984e056442c29ce</aircraft_apache>
|
||||
<aircraft_AR-234>c0c500c55706fc18d93817ebc3b6e83b</aircraft_AR-234>
|
||||
<aircraft_Arsenal-VG33>c883cde7942cdcfb8cd69c135c4d29f7</aircraft_Arsenal-VG33>
|
||||
<aircraft_Arup-S2>70db9ed1cb09e1442e22d020a9dc3069</aircraft_Arup-S2>
|
||||
<aircraft_as332>c62f9ee3f78c98a6342a6a337089fd10</aircraft_as332>
|
||||
<aircraft_ASK13>264d821437a558cf71c9209f466f6103</aircraft_ASK13>
|
||||
<aircraft_ASK21>27923bdc9f0f3ae3449f5d7a17744da5</aircraft_ASK21>
|
||||
<aircraft_ASK21-MI>023bbe168eb0babb4a68963edffc273b</aircraft_ASK21-MI>
|
||||
<aircraft_asw20>0926a8a021c4e11fa2610cbb5f6f11b3</aircraft_asw20>
|
||||
<aircraft_ATC>846d8156216e434e789f5d2b7432b68f</aircraft_ATC>
|
||||
<aircraft_ATC-ML>887c1bc8ab679604031f983ab6c67974</aircraft_ATC-ML>
|
||||
<aircraft_ATI-Resolution>915cd6323c113bb2a8b57e4c08900f3e</aircraft_ATI-Resolution>
|
||||
<aircraft_ATR-72-500>c0fe4169db9a338f5beec102f1efe301</aircraft_ATR-72-500>
|
||||
<aircraft_Avro-Arrow>4b2acc554752df97194e0da1a1c8638c</aircraft_Avro-Arrow>
|
||||
<aircraft_AVRO-IV-Triplane>9d3c4b4b66a7140628b79c4f142cc0f4</aircraft_AVRO-IV-Triplane>
|
||||
<aircraft_Avro-Lancaster>611d6172991766b32a43d19bfb06bbb2</aircraft_Avro-Lancaster>
|
||||
<aircraft_B-17>7cf94e2ee2c76783bf17c845e12e48cb</aircraft_B-17>
|
||||
<aircraft_B-1B>6407f6fd1bfe031b280639d20dfe100f</aircraft_B-1B>
|
||||
<aircraft_B-2>04db71541bc7099383524080a2c64012</aircraft_B-2>
|
||||
<aircraft_B-24-Liberator>2bdd09054c9c92088ff297d6358a05a8</aircraft_B-24-Liberator>
|
||||
<aircraft_B-25>51c6e9397e1e8fff65eb1d1671d18067</aircraft_B-25>
|
||||
<aircraft_B-36D-Peacemaker>3d1883d3213d2b5f7d39ec5221cd4eb2</aircraft_B-36D-Peacemaker>
|
||||
<aircraft_B-52F>d172dc57ce4e2c15f7f550a5c0c734a8</aircraft_B-52F>
|
||||
<aircraft_b1900d>db7301be7b428db2070e27a5fe7ee06e</aircraft_b1900d>
|
||||
<aircraft_b26>a71912ae798780eba390f9b27638b139</aircraft_b26>
|
||||
<aircraft_b29>7dd2ae465a7710921d11c6c18aa0c0e7</aircraft_b29>
|
||||
<aircraft_BAC-TSR2>6aaa660040bd40facf28fc68220b3cfc</aircraft_BAC-TSR2>
|
||||
<aircraft_BAe-125>2a3387f97647ad875060bac1284cfcbd</aircraft_BAe-125>
|
||||
<aircraft_Beagle-Pup>46a6f17c638e177421d1afc559b9d66a</aircraft_Beagle-Pup>
|
||||
<aircraft_beaufighter>50af4a2d301fafb2a3e13fe96e9215be</aircraft_beaufighter>
|
||||
<aircraft_beech99>6395fcaf780d6e43b4dd9f215a24e718</aircraft_beech99>
|
||||
<aircraft_Beechcraft-C18S>5a133a789694642b9f3e611ddf23d3d6</aircraft_Beechcraft-C18S>
|
||||
<aircraft_Beechcraft-Staggerwing>b668b91e67ef10757839da013faee44b</aircraft_Beechcraft-Staggerwing>
|
||||
<aircraft_Bell-222X>635dc4a39a43814f2885d59b1dda8a9d</aircraft_Bell-222X>
|
||||
<aircraft_Bell-P-39>aba5e103f315014925dff3b39bd2d648</aircraft_Bell-P-39>
|
||||
<aircraft_Bell-P-59>ba6e32553464e03fe6392303a2072631</aircraft_Bell-P-59>
|
||||
<aircraft_Bell-X1>3c10ccdf2775cad485bb394d5b1e56eb</aircraft_Bell-X1>
|
||||
<aircraft_Bell-XFL-1>167d03a6eafc1a3780f6fdf733fc7c6e</aircraft_Bell-XFL-1>
|
||||
<aircraft_Bernard-HV220>0579472d3185c8beba310aef9bf65f5d</aircraft_Bernard-HV220>
|
||||
<aircraft_bf109>cb732caa641493f07c4cc564018dd481</aircraft_bf109>
|
||||
<aircraft_Bleriot-125>21b170a0f9dae055d5c1d1af9946515e</aircraft_Bleriot-125>
|
||||
<aircraft_Bleriot-5190>4fdcfd3aa209318c07c779e408e81df2</aircraft_Bleriot-5190>
|
||||
<aircraft_Bleriot-SPAD-S.510>aef8c5f5f68349a7ae804df1d6d07e3f</aircraft_Bleriot-SPAD-S.510>
|
||||
<aircraft_bleriot-XI>e499504fcba1e95e0cca9c4418bfee23</aircraft_bleriot-XI>
|
||||
<aircraft_bluebird>a9af2d04a1e7bf279d135a4a06b11181</aircraft_bluebird>
|
||||
<aircraft_bo105>506a63476d00ef552b8adc3260ba1fa4</aircraft_bo105>
|
||||
<aircraft_bocian>9a3fd12ef60228dca05efa4ff694a882</aircraft_bocian>
|
||||
<aircraft_Boeing-247>152fcac32e4bb9f7fce5b6894b6da08b</aircraft_Boeing-247>
|
||||
<aircraft_Boeing-P26>97a640a4f9eddc33ac626f78adfaecb9</aircraft_Boeing-P26>
|
||||
<aircraft_Boeing314>f00599943616e14682c2baea90e6173a</aircraft_Boeing314>
|
||||
<aircraft_Bombardier-415>787d13e37c31fbf894d5a25091e4befc</aircraft_Bombardier-415>
|
||||
<aircraft_Br-761>78d4695d2466f50d3c45e0374809b386</aircraft_Br-761>
|
||||
<aircraft_Brabazon>6d0e61e40af698ea72e2978ed50e3a49</aircraft_Brabazon>
|
||||
<aircraft_Breda-B.Z.308>b3e9444c45cc9c445961b726429c0c7e</aircraft_Breda-B.Z.308>
|
||||
<aircraft_Breguet-XIX>a230231691ebc4df86e7d645f31a0f07</aircraft_Breguet-XIX>
|
||||
<aircraft_Buccaneer>84362d957e9dae0e5abc70ba4cb9816e</aircraft_Buccaneer>
|
||||
<aircraft_Bugatti>311a00f90c55c01980688c1d5504df64</aircraft_Bugatti>
|
||||
<aircraft_Burnelli-CBY-3>cb75a6990af600c666b02398cf77d6d1</aircraft_Burnelli-CBY-3>
|
||||
<aircraft_BV-141>a191302bdfb1faff1c6f2dd8a5494381</aircraft_BV-141>
|
||||
<aircraft_BV-170>258b971dd3041a49a816a2150d7e7125</aircraft_BV-170>
|
||||
<aircraft_C-160-Transall>695ce9bf3221055eecd24be01acb57e2</aircraft_C-160-Transall>
|
||||
<aircraft_C-2A>3c341ded96ce7c8832738c34c5c115f8</aircraft_C-2A>
|
||||
<aircraft_C130>c954a3ab900676c0cbabb1bada93754b</aircraft_C130>
|
||||
<aircraft_c150>270cabd6289080468d29a807f612cb4c</aircraft_c150>
|
||||
<aircraft_c172r>60bb07c7cefe930145d4b199b63842a7</aircraft_c172r>
|
||||
<aircraft_c182>fd61954ffdd247b47fec0fc9074aa40b</aircraft_c182>
|
||||
<aircraft_c182rg>171f7d74d45a50804c8111f5fab29543</aircraft_c182rg>
|
||||
<aircraft_c310>604cd9887e8f1c9011581348feca1e3c</aircraft_c310>
|
||||
<aircraft_c310u3a>80756d598e81a6a09217da9025e6284f</aircraft_c310u3a>
|
||||
<aircraft_C460>b465d263b244c5860ce010371032b5d3</aircraft_C460>
|
||||
<aircraft_C561>60cb1a6effe4e0023edd1bfdc109aed3</aircraft_C561>
|
||||
<aircraft_C684>e2881ea7546775db6847bb3890c04a03</aircraft_C684>
|
||||
<aircraft_Campini-Caproni-N1>68ec43ed98164bef020452e3758ec22f</aircraft_Campini-Caproni-N1>
|
||||
<aircraft_CanberraBI8>a865e922bec69cf8a6fe1f8d53dbc71b</aircraft_CanberraBI8>
|
||||
<aircraft_Cap10B>4a7cb6a6f5f6d71d5eb2da025b42d71f</aircraft_Cap10B>
|
||||
<aircraft_Cap10C>bd103f5fa8a8ac980b8c4ed3a041ff6b</aircraft_Cap10C>
|
||||
<aircraft_Caproni-C22J>d4eb3933d210d1a8f1deaf8b43a65960</aircraft_Caproni-C22J>
|
||||
<aircraft_Caproni-Ca3>0ad6cdbf91f37b6c71f94268914d2615</aircraft_Caproni-Ca3>
|
||||
<aircraft_Caproni-Stipa>d94119914089db0f7b6d43ddf20cb302</aircraft_Caproni-Stipa>
|
||||
<aircraft_Caravelle>826b017ad5bc1c77c65959367f41415f</aircraft_Caravelle>
|
||||
<aircraft_Carreidas>4cc78b3c9c421c382b4e197de6589535</aircraft_Carreidas>
|
||||
<aircraft_Caudron-G3>6c8b251c720301a00276f91db736ee85</aircraft_Caudron-G3>
|
||||
<aircraft_Caudron-G4>28ebd3b1236a53a0b15bf9c6f5cc79d6</aircraft_Caudron-G4>
|
||||
<aircraft_Cessna-208-Caravan>edbaa02c5b837b9522ad8d0fd7da81e8</aircraft_Cessna-208-Caravan>
|
||||
<aircraft_Cessna-421-Golden-Eagle>e16b7b135dbe3fa75539931c950116b6</aircraft_Cessna-421-Golden-Eagle>
|
||||
<aircraft_Cessna337>bf3b60a808daefd7b7374f934e7b10bf</aircraft_Cessna337>
|
||||
<aircraft_ch47>d46d6e08cd90412088abffe2dbd03982</aircraft_ch47>
|
||||
<aircraft_ch53e>55d564ff1b335a723d144e423b9a3c10</aircraft_ch53e>
|
||||
<aircraft_Cirrus-SR22>a3bbd80a8c11bea16f567eafa898db8f</aircraft_Cirrus-SR22>
|
||||
<aircraft_Citation>c6f74c5596f959608e1810004abba534</aircraft_Citation>
|
||||
<aircraft_Citation-Bravo>a6743e193bb01776107fec98595555e4</aircraft_Citation-Bravo>
|
||||
<aircraft_CitationX>8bf718df53a6af7777f087a302641061</aircraft_CitationX>
|
||||
<aircraft_Coanda-1910>b66f175629a52396dd1db3f1718d2028</aircraft_Coanda-1910>
|
||||
<aircraft_colditz>77100ce686eee7ae2b5950df44a38709</aircraft_colditz>
|
||||
<aircraft_Commonwealth-Ca-12>f132805e11b1c1e60908080b9b6533ad</aircraft_Commonwealth-Ca-12>
|
||||
<aircraft_ComperSwift>8b227cd83d5f1f3b3b44bb7b46714349</aircraft_ComperSwift>
|
||||
<aircraft_Concorde>566f1dc35ae741cdeee125111f1e0c20</aircraft_Concorde>
|
||||
<aircraft_Convair-XFY-1-Pogo>633550eae44633a9b23777ffab527f1b</aircraft_Convair-XFY-1-Pogo>
|
||||
<aircraft_couzinet70>d8fa7f026fc404ad20b7c7f6a11619ee</aircraft_couzinet70>
|
||||
<aircraft_cri-cri>bc2267347bc48ba2377926a7a6515274</aircraft_cri-cri>
|
||||
<aircraft_CRJ-200>0d500b113ae2d633e5f0bf36a1d19fd9</aircraft_CRJ-200>
|
||||
<aircraft_CRJ700-family>d935f718bed4a71069122fe5214ecd2e</aircraft_CRJ700-family>
|
||||
<aircraft_Curtiss-Jenny>6062a91295fbf99801e65197a71451c5</aircraft_Curtiss-Jenny>
|
||||
<aircraft_Curtiss-Model-F>8ca56323ab3db01ec034f231490a7702</aircraft_Curtiss-Model-F>
|
||||
<aircraft_Curtiss-P40>a0d00a78d80e4a621a1cfb55c0658fe3</aircraft_Curtiss-P40>
|
||||
<aircraft_D510>8b09cc7658164d311f4e70e36f463cde</aircraft_D510>
|
||||
<aircraft_D520>b967ca884dd02b37ad9c247d31bdf1c7</aircraft_D520>
|
||||
<aircraft_DaSH>f9c33778a3805892fbd0e6de35e54e91</aircraft_DaSH>
|
||||
<aircraft_Dassault-Mystere-IV>387fd1c59b2e5934ffcd888df39b7174</aircraft_Dassault-Mystere-IV>
|
||||
<aircraft_Dauphin>bdc3b2e695db1588827d000b55bbebda</aircraft_Dauphin>
|
||||
<aircraft_DC-10-30>1d37211f993a920b0806b95db0f8ea7c</aircraft_DC-10-30>
|
||||
<aircraft_dc2>77f9e6a9e1647dcd012966af7df1d4be</aircraft_dc2>
|
||||
<aircraft_dc6>dbfd9548db8318098daa75733171a18e</aircraft_dc6>
|
||||
<aircraft_dc8-63>70cff7394ced9ab348653ad82ece3c10</aircraft_dc8-63>
|
||||
<aircraft_dc8-73>26883edc54c7a02e208ce51e7b964e2e</aircraft_dc8-73>
|
||||
<aircraft_Deperdussin>00fc8120294619b97ccf0e04a6145c1f</aircraft_Deperdussin>
|
||||
<aircraft_DerKleineUhu>9003650773fd4933b40089d146484045</aircraft_DerKleineUhu>
|
||||
<aircraft_Deuche>033799e2157ac9ffc6ac04fcdfeafe04</aircraft_Deuche>
|
||||
<aircraft_DG-101G>02e81c7a33551c2581f8d5767e464518</aircraft_DG-101G>
|
||||
<aircraft_DH-106>f7ac35642502a83a265f7b6594650279</aircraft_DH-106>
|
||||
<aircraft_DH-88>be3e5fcef3000c72a2d85fb9eb827793</aircraft_DH-88>
|
||||
<aircraft_DH-89>c745759b0e259323b20ba2e535284e7d</aircraft_DH-89>
|
||||
<aircraft_DH-91>8b24f65ff28f7c66e65bcf7025582575</aircraft_DH-91>
|
||||
<aircraft_dhc1>14b8d09e2debfdfd9cac81b8b67c9498</aircraft_dhc1>
|
||||
<aircraft_dhc2>ff6f3470289772182d931daa00f6057f</aircraft_dhc2>
|
||||
<aircraft_dhc3>a0506714e972c2a58f745c6bd7cc4fe2</aircraft_dhc3>
|
||||
<aircraft_dhc4>4a792858aa65aada7cb91a47a9cf8c5d</aircraft_dhc4>
|
||||
<aircraft_dhc6>81fb6e7b8ff50d43180bb758d1a56121</aircraft_dhc6>
|
||||
<aircraft_dhc8>cca58285c8c814dfe923aaec656b1d9c</aircraft_dhc8>
|
||||
<aircraft_Diamond-Da40>26885d6e6a849ad9dd54829baa26daee</aircraft_Diamond-Da40>
|
||||
<aircraft_Diamond-Da42>e9992fcecbc66640a932c1c8fb7e71ae</aircraft_Diamond-Da42>
|
||||
<aircraft_DO-228>8915f9465c563740f9f8f2cf32f1dd74</aircraft_DO-228>
|
||||
<aircraft_DO-26>80757f34ea04417b6b30d65092ce50ab</aircraft_DO-26>
|
||||
<aircraft_DO-335>ba8bbc9e04405db298beb9c24c6200c3</aircraft_DO-335>
|
||||
<aircraft_DO-X>41356deabb2cd689393f36b96123a330</aircraft_DO-X>
|
||||
<aircraft_Douglas-Dc3>b57c14a1791a20bccbf23db826a22dbb</aircraft_Douglas-Dc3>
|
||||
<aircraft_Douglas-Dolphin>578771e25e6d7d81e5574d8cd1d19de0</aircraft_Douglas-Dolphin>
|
||||
<aircraft_DR400>01c814d7ddeb0adcee0ed58022ebf6a8</aircraft_DR400>
|
||||
<aircraft_DR400-dauphin>259cd05cfbf4b80b2cb4be07cf4bf781</aircraft_DR400-dauphin>
|
||||
<aircraft_Dragonfly>012f8917ef6d7ec50d8a73c0508e5b47</aircraft_Dragonfly>
|
||||
<aircraft_Dromader>9f77b8fbf981c4d761d8c497b6ef0868</aircraft_Dromader>
|
||||
<aircraft_Dunne-D.5>48795402cda50957be7b7504b4d82389</aircraft_Dunne-D.5>
|
||||
<aircraft_E-2C>d015100dfb5381135d221f41b293584d</aircraft_E-2C>
|
||||
<aircraft_E3B>894c16ccfa5aed2778c7be4873947b69</aircraft_E3B>
|
||||
<aircraft_eastbourne_mono>a99c8114ca48074fea2c675a8e6908e0</aircraft_eastbourne_mono>
|
||||
<aircraft_ec130>684d979f81bf15b2adf47b52d6ca21f7</aircraft_ec130>
|
||||
<aircraft_ec135>39631381049db9e54655c499f91bfb31</aircraft_ec135>
|
||||
<aircraft_Embraer-ERJ-145>ef5ed515fe8f93876137bb6b27f3b158</aircraft_Embraer-ERJ-145>
|
||||
<aircraft_ercoupe>bdaa474d4be6e51b21266ce0c8782c2c</aircraft_ercoupe>
|
||||
<aircraft_Etrich-Taube>f6ba735798172b43abf417c80c1c4db4</aircraft_Etrich-Taube>
|
||||
<aircraft_eurofighter>0f915d06528b1cc2dcc16f7be3b9ab37</aircraft_eurofighter>
|
||||
<aircraft_extra500>72a8b154cda42a2ec507b6a4c604afcb</aircraft_extra500>
|
||||
<aircraft_F-106-dart>84bfa325c11d56920062e8516bfc146e</aircraft_F-106-dart>
|
||||
<aircraft_F-117>ba904d06c2ddb28a7fd3f95ac344de7a</aircraft_F-117>
|
||||
<aircraft_f-14b>3c0963e6203c4a6315155012bbbb8096</aircraft_f-14b>
|
||||
<aircraft_F-15>43f556905826c6ad5c80af409eb8a76c</aircraft_F-15>
|
||||
<aircraft_F-35B>e1875c6efdc7ffe1160d8e64ac5f5fd7</aircraft_F-35B>
|
||||
<aircraft_F-86>ea67ec6bb6c981dbbd391003f997c6ef</aircraft_F-86>
|
||||
<aircraft_F-8E-Crusader>41b4502a287018e27402925094324209</aircraft_F-8E-Crusader>
|
||||
<aircraft_f16>25805162fbd9d4d00e09c814f0beef9b</aircraft_f16>
|
||||
<aircraft_f18>45264d8293d22533f56f571283940754</aircraft_f18>
|
||||
<aircraft_F4U>fb47e4425240141a45818dcdc8060a4b</aircraft_F4U>
|
||||
<aircraft_F6F-Hellcat>b4fcbc6e73565001d25f3cd64fb85a77</aircraft_F6F-Hellcat>
|
||||
<aircraft_F7F-Tigercat>0ea6ad997b8595f97530d9aed5529ec9</aircraft_F7F-Tigercat>
|
||||
<aircraft_F80C>9a7c5ac1aabe992abf14fd4b53c1712c</aircraft_F80C>
|
||||
<aircraft_F9F-Panther>305fc09e91c52fefd2b67d6925baff38</aircraft_F9F-Panther>
|
||||
<aircraft_fa223>3746de4faf66266399a9273321088ce2</aircraft_fa223>
|
||||
<aircraft_Fairchild-C119>ec397cdc0f61d78ecc28d2cc564becd6</aircraft_Fairchild-C119>
|
||||
<aircraft_Fairchild-Metroliner>3248a3f496cc146fcd95c61ec2538ae7</aircraft_Fairchild-Metroliner>
|
||||
<aircraft_Fairey-Gannet>96e43cd67c0c8b9fd6e158a3ee46fbdc</aircraft_Fairey-Gannet>
|
||||
<aircraft_Falcon-50>6d78633d200d8f945be6400027116539</aircraft_Falcon-50>
|
||||
<aircraft_Farman-III>3e0a4af617e2064e78cee25e1d8af653</aircraft_Farman-III>
|
||||
<aircraft_Farman-IV>42f45908ac131a855f66e63c09279562</aircraft_Farman-IV>
|
||||
<aircraft_Fiat-G55>15f03458e112d4d7d3ff674dc20286c2</aircraft_Fiat-G55>
|
||||
<aircraft_Fiat-G91>a3854718af2cf6c4c0512a166e283b4c</aircraft_Fiat-G91>
|
||||
<aircraft_FK9MK2>24144321fdadaf71e81f8b014ad0e16b</aircraft_FK9MK2>
|
||||
<aircraft_fkdr1>2294512dc1cdb63a8b90a21ba48875c7</aircraft_fkdr1>
|
||||
<aircraft_flash2a>c56ee7fbdb10b1ba979d019cc26972cf</aircraft_flash2a>
|
||||
<aircraft_Focke-Wulf-F19-ente>8bd5f800b24dbfc37f59fe368a748af1</aircraft_Focke-Wulf-F19-ente>
|
||||
<aircraft_Focke-Wulf-Ta.154>f926af126c01eabd3ceb0398b178519a</aircraft_Focke-Wulf-Ta.154>
|
||||
<aircraft_Fokker-Eindecker-EIII>29cd9e7ea06489595979f3df518813dd</aircraft_Fokker-Eindecker-EIII>
|
||||
<aircraft_Fokker-G1>ea6025e2b6cdffc86764c5ee5a949c9a</aircraft_Fokker-G1>
|
||||
<aircraft_Fokker-S-11>c3f68417e01ab653e66131bd446f8940</aircraft_Fokker-S-11>
|
||||
<aircraft_Fokker-Spin>2fc955ad2ecb4ba0a7899097e7e4b226</aircraft_Fokker-Spin>
|
||||
<aircraft_fokker100>83874804ebae4b77f6ac92f55c19ba91</aircraft_fokker100>
|
||||
<aircraft_fokker50>da5fc6e9761203e6dd26dc3f01a2fe68</aircraft_fokker50>
|
||||
<aircraft_followme>6b17d6d7bc78b5424420d47c0d737fa9</aircraft_followme>
|
||||
<aircraft_Ford-Trimotor>83743f288a09c89716ac2a2e212b11bc</aircraft_Ford-Trimotor>
|
||||
<aircraft_Fouga-Magister>866329f60e90f3404a6bace54e733b73</aircraft_Fouga-Magister>
|
||||
<aircraft_fw190>449953e8d06e61e78e94e520d8fbc3e3</aircraft_fw190>
|
||||
<aircraft_Fw200>5179bd127ee44112ec06887e322725aa</aircraft_Fw200>
|
||||
<aircraft_Fw61>049759aaa0c615f71b0e1e2d683cb3ba</aircraft_Fw61>
|
||||
<aircraft_G-164>977f70220ecee03ef7367b940956122a</aircraft_G-164>
|
||||
<aircraft_Gee-Bee>bf993f8a5499538d2b5f5f5ec0c7574d</aircraft_Gee-Bee>
|
||||
<aircraft_Gloster-Gladiator>65223229f5f8adc17c534412fb1b2bc8</aircraft_Gloster-Gladiator>
|
||||
<aircraft_Gloster-Meteor>9905dc7569bc1e9cf750e47cc138dbeb</aircraft_Gloster-Meteor>
|
||||
<aircraft_Gloster-Whittle>ef530cb8d0f3b53b83d993f4284bc4c3</aircraft_Gloster-Whittle>
|
||||
<aircraft_Gotha-G-V>d18ed659fb34df8e078b36d0156de731</aircraft_Gotha-G-V>
|
||||
<aircraft_Grob-Astir>57ada6ce17e8dda569e49ef29a517b90</aircraft_Grob-Astir>
|
||||
<aircraft_Grob-G109>65c28732f4909889ca9739953c7b2032</aircraft_Grob-G109>
|
||||
<aircraft_Grob-G115>82ca3e94ee5a1ee711fbc73e7ab99645</aircraft_Grob-G115>
|
||||
<aircraft_Grob-Gf200>b80921cb1ec91813ba6912abf8d3d73c</aircraft_Grob-Gf200>
|
||||
<aircraft_Grumman-American-AA1>40f6523b7cc0aff71281820d54bdaa0f</aircraft_Grumman-American-AA1>
|
||||
<aircraft_H-21C-Shawnee>515e08d2a12b2cc1891f23e086aa5933</aircraft_H-21C-Shawnee>
|
||||
<aircraft_H1-Racer>d8250d2d9f842108ffed965ced81ab64</aircraft_H1-Racer>
|
||||
<aircraft_H4-Hercules>34ea914ec8c9f7c85ba3c243c6d0f981</aircraft_H4-Hercules>
|
||||
<aircraft_Handley-Page-Halifax>837d0bc1db372b8d18e251fb63aa13ea</aircraft_Handley-Page-Halifax>
|
||||
<aircraft_Hansajet>98a417480a3126432d9214fe0efb83c9</aircraft_Hansajet>
|
||||
<aircraft_harrier>568eeccd7ffc3b08937fdf2da81a972a</aircraft_harrier>
|
||||
<aircraft_Harrier-GR1>8f90009d9f8c66ba0dafc1c05ff2c685</aircraft_Harrier-GR1>
|
||||
<aircraft_Harrier-GR3>b3d6038ff416a64372b663e9f3ccc137</aircraft_Harrier-GR3>
|
||||
<aircraft_Hawker-Siddeley-Nimrod>e78cd169d9423dc9a9126d51fbeeb91e</aircraft_Hawker-Siddeley-Nimrod>
|
||||
<aircraft_He-111>febb50152f339e23040815432e8fd6d4</aircraft_He-111>
|
||||
<aircraft_He162>a27b2dd3efe6a362d135d55eca70d134</aircraft_He162>
|
||||
<aircraft_Heinkel-He-111>941ab65d0ee6a8c0578e87b8d881ffc0</aircraft_Heinkel-He-111>
|
||||
<aircraft_Heinkel-He-177>3bc698cc3b8937609e715c12fb135ca0</aircraft_Heinkel-He-177>
|
||||
<aircraft_Heinkel-He-178>8a646c02ac858485f683301e5d98adb5</aircraft_Heinkel-He-178>
|
||||
<aircraft_Heinkel-He-280>f4656701178b9d1eea30aa73b6a96ea2</aircraft_Heinkel-He-280>
|
||||
<aircraft_Heston-Type5>11ef72971dce2d4b47f9899fabc4e591</aircraft_Heston-Type5>
|
||||
<aircraft_HM-14>aa1c16c7731e99ebc6cd536ce26daa14</aircraft_HM-14>
|
||||
<aircraft_Hornet>5dacabf98fe85149246cd5fc9bae6c39</aircraft_Hornet>
|
||||
<aircraft_Horsa>1ddf68bca0c4a97d263a2d1718f87d2e</aircraft_Horsa>
|
||||
<aircraft_Horten-Ho-IX>e8e04eb1d9bd25e270944775d8cb4100</aircraft_Horten-Ho-IX>
|
||||
<aircraft_HS-P-75>90f738b3a6362f787e2170cb3d7317f0</aircraft_HS-P-75>
|
||||
<aircraft_Hughes-XF11>bcf549f662ba17ac5896ef38b824f13e</aircraft_Hughes-XF11>
|
||||
<aircraft_Hunter>608118d1e8019c92a22c275b8ce02c4a</aircraft_Hunter>
|
||||
<aircraft_HUP-Retriever>5a2683f3d5a170495dc0ed3ed8cfa3f2</aircraft_HUP-Retriever>
|
||||
<aircraft_Hurricane>0f64845ba2b2a4bc6a5f5637d261b93b</aircraft_Hurricane>
|
||||
<aircraft_Icaro_MRX13>5f873b418694a01d049664ae58ad69a8</aircraft_Icaro_MRX13>
|
||||
<aircraft_IL-2>cdc9eeae48d8760204735cf3dfdfbec9</aircraft_IL-2>
|
||||
<aircraft_j22>14d705864d455ec73ca9c373f6d61d58</aircraft_j22>
|
||||
<aircraft_J3Cub>f978f4a979edc6b3ac3c6b0cbd631c83</aircraft_J3Cub>
|
||||
<aircraft_j7w>b777fc0d1a2c85ce6c0a03dfd90df48b</aircraft_j7w>
|
||||
<aircraft_JA37>ef141db8c2469b1421c8e74f018ee8a4</aircraft_JA37>
|
||||
<aircraft_Jaguar>7a0a5d5f93e34dd40fcdce3f06848908</aircraft_Jaguar>
|
||||
<aircraft_JAS39-Gripen>ed3685660909e7e831d7711a2cc7b7b0</aircraft_JAS39-Gripen>
|
||||
<aircraft_jeep>59341e0675583a826c34c625ba277345</aircraft_jeep>
|
||||
<aircraft_jetman>67a0cbf1e934dd6552cf3f231ed65964</aircraft_jetman>
|
||||
<aircraft_Jodel-D140>0cfed1923e5d2b849760df5ced30a175</aircraft_Jodel-D140>
|
||||
<aircraft_JT-5B>0650d1a62cce431fa07e64bf8845a904</aircraft_JT-5B>
|
||||
<aircraft_Ju-87>91a6f9e779d641b451efa777b6f81e81</aircraft_Ju-87>
|
||||
<aircraft_Ju-88>ebdd6f04edccd2205bcaed1e845b567d</aircraft_Ju-88>
|
||||
<aircraft_ju52>ee7f03a89cabb1370183f8a88dad1e9d</aircraft_ju52>
|
||||
<aircraft_Junkers-F13>f88670ae7d834818ba14d71a7e0036e3</aircraft_Junkers-F13>
|
||||
<aircraft_Junkers-G.38ce>7ad891738873394a7626882fd86e2031</aircraft_Junkers-G.38ce>
|
||||
<aircraft_Junkers-Ju-390>be9047b6412830adcf9a7d68cb4574d1</aircraft_Junkers-Ju-390>
|
||||
<aircraft_Junkers-W34>b5e96c226c4a2277b34dee97efc1d960</aircraft_Junkers-W34>
|
||||
<aircraft_K-7>cb160921e2c703bbbdafcb51d49c266f</aircraft_K-7>
|
||||
<aircraft_K5Y1>f72439b0db6a44fde139cb7651c28207</aircraft_K5Y1>
|
||||
<aircraft_Ka-50>96aae67efd76fb6bfce1a97b1fbdbefd</aircraft_Ka-50>
|
||||
<aircraft_Katana>151fbc5f85a7acd78039d2f074901028</aircraft_Katana>
|
||||
<aircraft_Kawasaki-Ki-61-Hien>4ab8429c7200f96c144439fe50cda12d</aircraft_Kawasaki-Ki-61-Hien>
|
||||
<aircraft_KC135>28519bdf05d7b1c5601ebfe9b7d95c0d</aircraft_KC135>
|
||||
<aircraft_Ki-84>fbee5f8f188262cf1e09c168dd1014db</aircraft_Ki-84>
|
||||
<aircraft_KM>3031820f648fe2fb15f8c9d64c104387</aircraft_KM>
|
||||
<aircraft_kodiak>947daecf702214b7708c8d7df872366b</aircraft_kodiak>
|
||||
<aircraft_L-1011-500>14670bbba47068cc5914c399c51a20e3</aircraft_L-1011-500>
|
||||
<aircraft_l39>1d42f9adf23bf70ef1f9ba1695b9f794</aircraft_l39>
|
||||
<aircraft_La-5>75204b0421e9835bf3ac3d2a0d198163</aircraft_La-5>
|
||||
<aircraft_Lancair-235>6fbd208db0830b462fe2d105d1924f1e</aircraft_Lancair-235>
|
||||
<aircraft_LATE-29>5ad79d5b9a17f3ac79b71722547fb6ff</aircraft_LATE-29>
|
||||
<aircraft_Late-631>421b4ec83fe86c82e0bb952d3ee08780</aircraft_Late-631>
|
||||
<aircraft_Leduc-022>2d3c15a8151e86b497900f6873b1875b</aircraft_Leduc-022>
|
||||
<aircraft_Lightning>b80a9a8c89b05c4fa22a314ea56b32ab</aircraft_Lightning>
|
||||
<aircraft_Lionceau>93a573bcf722ce69de872674b3f9dd27</aircraft_Lionceau>
|
||||
<aircraft_Lockheed-Martin-FA-22A-Raptor>97c2da3770e378b72637b09c0475156f</aircraft_Lockheed-Martin-FA-22A-Raptor>
|
||||
<aircraft_Lockheed-NF104>572acc2315b077411699eba35c0655d1</aircraft_Lockheed-NF104>
|
||||
<aircraft_Lockheed-NF104A>41347e33250b355077aba64c671a44ce</aircraft_Lockheed-NF104A>
|
||||
<aircraft_Lockheed-P38>53cd0af0a81de17378a7d3201c31dbb9</aircraft_Lockheed-P38>
|
||||
<aircraft_Lockheed-SR71>99485aa18c25c0e6537334d63ccfe2c6</aircraft_Lockheed-SR71>
|
||||
<aircraft_Lockheed-U-2S>b00db640f9f0f490b0bfa7d6d8b40163</aircraft_Lockheed-U-2S>
|
||||
<aircraft_Lockheed-Vega>04e530018ec557294dd90128fc0c4a56</aircraft_Lockheed-Vega>
|
||||
<aircraft_Lockheed1049>99539707fa1c283b6513be48996d8d14</aircraft_Lockheed1049>
|
||||
<aircraft_Lockheed1049h>8da4141b5716e4321d1d5dcf3cfd30e6</aircraft_Lockheed1049h>
|
||||
<aircraft_Long-EZ>6e5a8b2abc701632f9b9ab7a839eee4d</aircraft_Long-EZ>
|
||||
<aircraft_Lynx-WG13>9add8ac0325547a52fa53e03b06d23b9</aircraft_Lynx-WG13>
|
||||
<aircraft_M-XE>1978498650f9f5ae335cfd702a6d16f6</aircraft_M-XE>
|
||||
<aircraft_Macchi-Castoldi-MC72>6952026a71d24cf0b11baca0320ab087</aircraft_Macchi-Castoldi-MC72>
|
||||
<aircraft_Macchi-M33>90dc0d1bce4c19822312f51be82e9c98</aircraft_Macchi-M33>
|
||||
<aircraft_marchetti>b6959644da3e1acbdd2f63af0cc529f0</aircraft_marchetti>
|
||||
<aircraft_Martin-Baker-MB5>5c21bdb968a38b57b911aa998b9db99d</aircraft_Martin-Baker-MB5>
|
||||
<aircraft_MB326>1a61bc6d32a3ed512b51535c46dc6991</aircraft_MB326>
|
||||
<aircraft_MD-312-Flamant>be65efca7b7d7fc246c373e391996978</aircraft_MD-312-Flamant>
|
||||
<aircraft_MD11>e772e7fae851948c6f6b19c0191821aa</aircraft_MD11>
|
||||
<aircraft_ME-209-V1>3de79c61240e8e04a24d95c707a61a2b</aircraft_ME-209-V1>
|
||||
<aircraft_ME-262>9960374b772e64e5ad75e0d3b6e12f08</aircraft_ME-262>
|
||||
<aircraft_ME-262HGIII>3dfa621d920cecce3585b0f1ccb6be72</aircraft_ME-262HGIII>
|
||||
<aircraft_me163>687309052c27966bd4d3bbd023237c17</aircraft_me163>
|
||||
<aircraft_me323>0d615e9e715d3d4e150e836fbf43f426</aircraft_me323>
|
||||
<aircraft_Messerschmitt-BF110>39b9d8b0a4aafa4e1b25992520deb011</aircraft_Messerschmitt-BF110>
|
||||
<aircraft_Messerschmitt-Libelle>ed7ad8c54b6c2d9d1727e85a1a198a31</aircraft_Messerschmitt-Libelle>
|
||||
<aircraft_Messerschmitt-P1101>3b989b232dd121eff6b0b230e9e85f6c</aircraft_Messerschmitt-P1101>
|
||||
<aircraft_MFI-9>a566bad5dc6de5bc8d782c4f292e34ed</aircraft_MFI-9>
|
||||
<aircraft_MiG-15>9bb9d2c8983b99f4f74e063f3d1e3479</aircraft_MiG-15>
|
||||
<aircraft_MiG-21bis>d749c64a1fa96fbb0f13fc3d41b646e9</aircraft_MiG-21bis>
|
||||
<aircraft_Mig-29>c6b9271b94abdf0770612a5cf4555f91</aircraft_Mig-29>
|
||||
<aircraft_Mil-Mi-12>e1d83cafee3b3cecfdc3e473913df264</aircraft_Mil-Mi-12>
|
||||
<aircraft_Mil-Mi-24>9fe6b04de733a20290141310f02abdcf</aircraft_Mil-Mi-24>
|
||||
<aircraft_Mirage-2000>7bf582dfc110cfe38d616b1cdeed91ee</aircraft_Mirage-2000>
|
||||
<aircraft_mirage2000>faa0e38bdadaadb61fa28e968f8a2122</aircraft_mirage2000>
|
||||
<aircraft_Mirage_F1>dc188baadc7e6b3033845cfd48a14163</aircraft_Mirage_F1>
|
||||
<aircraft_MirageIII>9f814e7ec8180ca71bbaf721d9337e70</aircraft_MirageIII>
|
||||
<aircraft_MirageIV>a969aedf03beddd8ee89367d6179e1a4</aircraft_MirageIV>
|
||||
<aircraft_mosquito>15eac7459f9aeafabdce72df42a4ba69</aircraft_mosquito>
|
||||
<aircraft_MPCarrier>280758b9c9b1ec90f2010f1b1ab06ba7</aircraft_MPCarrier>
|
||||
<aircraft_MRJ>ad879791f1e9d0e2d719d6a4518bbe2c</aircraft_MRJ>
|
||||
<aircraft_MS-406>4507e58972e6bc69ba4f46ea3db455ec</aircraft_MS-406>
|
||||
<aircraft_Nakajima-B5N>02e681d40a2427610dd55c643e89b01d</aircraft_Nakajima-B5N>
|
||||
<aircraft_Nieuport-11>701b0401fb152e87a40c8b5babe87798</aircraft_Nieuport-11>
|
||||
<aircraft_Noratlas>b177adbf225feca2f7d39f80d5acc352</aircraft_Noratlas>
|
||||
<aircraft_Nord-1405-Gerfaut-II>a862bcf397791708ef2e0441282b2b69</aircraft_Nord-1405-Gerfaut-II>
|
||||
<aircraft_Nord-2502>c6f4dc65ba8177e50ef5742b3ecb52b7</aircraft_Nord-2502>
|
||||
<aircraft_Nordstern>6df28cb4a7d5e8907391c3ed8e70b6e0</aircraft_Nordstern>
|
||||
<aircraft_North-American-T28D-Trojan>5fee1165f23a11eeca4d24d766117377</aircraft_North-American-T28D-Trojan>
|
||||
<aircraft_North-American-T6-Texan>7ee82c752779d1c51f7b92660006aad2</aircraft_North-American-T6-Texan>
|
||||
<aircraft_Northrop-P61>23a394d7e36aa653bff9b32fc9548250</aircraft_Northrop-P61>
|
||||
<aircraft_Northrop-xb35>e4ec374be03638c10a88f351e8f09bad</aircraft_Northrop-xb35>
|
||||
<aircraft_ogel>26e51eabb21a9a71f1b5a685e3061843</aircraft_ogel>
|
||||
<aircraft_OH-1>49259a0e7725bb2c6809e1aae15e8fac</aircraft_OH-1>
|
||||
<aircraft_OH-58D>40801a1693b0b8bd33178d4a5bf67765</aircraft_OH-58D>
|
||||
<aircraft_ornithopter>7b0c70f7b8de3e1a5c19d32c36fa7d00</aircraft_ornithopter>
|
||||
<aircraft_OV10>74faff4f12efb353ccc61689fe96c46c</aircraft_OV10>
|
||||
<aircraft_P-38-Lightning>43c98dfe30fecc4c2448dc51750154ee</aircraft_P-38-Lightning>
|
||||
<aircraft_P130UL>ea0a540d06226687e3409c1226a1cc1d</aircraft_P130UL>
|
||||
<aircraft_P180>ab8760c0219835fe97dcbbf698b39fa4</aircraft_P180>
|
||||
<aircraft_P47>cc9b6238b260d924338d2c4ee2dafc95</aircraft_P47>
|
||||
<aircraft_p51d>7caa4abbdb5dba23edbdc02cf2693909</aircraft_p51d>
|
||||
<aircraft_pa22>da2990b33cef4afe7d629530b274632a</aircraft_pa22>
|
||||
<aircraft_pa24-250>65a95dd87096e2377dff6fe917befb8a</aircraft_pa24-250>
|
||||
<aircraft_pa28-161>02f4a01e218da00e8969d4ae52c84193</aircraft_pa28-161>
|
||||
<aircraft_PaperAirplane>2b7fbfc1efdf6ab2663e8b3d7cd3daed</aircraft_PaperAirplane>
|
||||
<aircraft_Parachutist>79da74f4e265f5290b4cf35b740663a7</aircraft_Parachutist>
|
||||
<aircraft_paraglider>6531e09545716af63e4ef5cf8feb8ec1</aircraft_paraglider>
|
||||
<aircraft_payen-pa100>2f86aa5353798f3a4202e403bfa12c02</aircraft_payen-pa100>
|
||||
<aircraft_payen-pa350cd>b6e5e2bb9985effc63bdcb2177ec681b</aircraft_payen-pa350cd>
|
||||
<aircraft_PBY-Catalina>937f55e89ec3df58c2d0339f9a1dd622</aircraft_PBY-Catalina>
|
||||
<aircraft_PC-12>70352371bec5bee2af6bfa7fceb7da5e</aircraft_PC-12>
|
||||
<aircraft_PC-21>a53d16394c2492eb0a713ecfd8dbaf8e</aircraft_PC-21>
|
||||
<aircraft_PC-6>b4fbd66018b94d83d11e3e6e7e0fac1d</aircraft_PC-6>
|
||||
<aircraft_PC-9M>7c90665c0c85a3e81b15a0ea69befeeb</aircraft_PC-9M>
|
||||
<aircraft_pc7>6eea7be83224abc9a1c3da0ce2fe6c82</aircraft_pc7>
|
||||
<aircraft_Percival-Mew-Gull>e2e0f33e2d38ad747f5c738230439ad6</aircraft_Percival-Mew-Gull>
|
||||
<aircraft_Piaggio-P166>66de4194f057e4a5248d19c5d51f88ca</aircraft_Piaggio-P166>
|
||||
<aircraft_Piaggio-Pegna-Pc-7>6944e2533d7ddca2752df6300a281b16</aircraft_Piaggio-Pegna-Pc-7>
|
||||
<aircraft_Pioneer-200>8e89696bf062126e4fe969a65ea5da1f</aircraft_Pioneer-200>
|
||||
<aircraft_Piper-PA-18>466c8c681f2c6c942668d769e79defba</aircraft_Piper-PA-18>
|
||||
<aircraft_Piper-PA-28>f7f176d0ff24d09134c43f0e0bc57d5b</aircraft_Piper-PA-28>
|
||||
<aircraft_Piper-PA-32>601545618b8fe3c210b4514a25242faf</aircraft_Piper-PA-32>
|
||||
<aircraft_pittss1c>427efb1a07d99ca6c99698de322b7d74</aircraft_pittss1c>
|
||||
<aircraft_Polikarpov-I16>3926f7b7e584ad63327a622dbac60564</aircraft_Polikarpov-I16>
|
||||
<aircraft_Pond-Racer>46e6876c63888a593dd46307b7fe0965</aircraft_Pond-Racer>
|
||||
<aircraft_Potez-630>228dab05bac8112a51265a509d28adc3</aircraft_Potez-630>
|
||||
<aircraft_Pterodactyl>aa747cdb68e4ce5bcf3fcf3a7fa9b371</aircraft_Pterodactyl>
|
||||
<aircraft_Pterosaur>fec9ddaa76f650624821341e07c32ef5</aircraft_Pterosaur>
|
||||
<aircraft_pushback>8fa3ff17dbf4f5216d2b038af30b6d4b</aircraft_pushback>
|
||||
<aircraft_Quickie>9e12e7ae2a644e77749efb5d5c4d0917</aircraft_Quickie>
|
||||
<aircraft_R22>7c66503ed0253f16ad021be72e4abfa7</aircraft_R22>
|
||||
<aircraft_R44>4db8a423cab299263b5139e0b44c4884</aircraft_R44>
|
||||
<aircraft_RAF-S-E-5>267a979bb7fcadac5698365c158f8fbf</aircraft_RAF-S-E-5>
|
||||
<aircraft_rah-66>14d8af5d3bc22ac49c5bdfcb8f63c9d8</aircraft_rah-66>
|
||||
<aircraft_rallye-MS893>7afb876e7a2e7b7bfaa8619bf0c07265</aircraft_rallye-MS893>
|
||||
<aircraft_Rascal>640eafc8068633c0e48ed3a569d18870</aircraft_Rascal>
|
||||
<aircraft_RV-6A>27238520cd1123eb6e832489ed6d5a65</aircraft_RV-6A>
|
||||
<aircraft_Ryan-Navion>e64d386ede9f5d1ab93bbe212246086f</aircraft_Ryan-Navion>
|
||||
<aircraft_Ryan-PT22>dee77f1d0d3de7f0ce6859006e0ba642</aircraft_Ryan-PT22>
|
||||
<aircraft_Ryan-SoSL>93e380e1b639a5d063be34521ef058a1</aircraft_Ryan-SoSL>
|
||||
<aircraft_S-51-Dragonfly>fa4c3f5a64725039c6ac69dc817d0861</aircraft_S-51-Dragonfly>
|
||||
<aircraft_SaabJ35F>d9c356d0f282204a451c7acb86a0df95</aircraft_SaabJ35F>
|
||||
<aircraft_santa>cd6232d913be2a512d2e8fcae806afad</aircraft_santa>
|
||||
<aircraft_Saunders-Roe-Princess>a6cef52c80b2fd0ebc43e26183d9a668</aircraft_Saunders-Roe-Princess>
|
||||
<aircraft_seahawk>792aa8e491c51b10898600e5fce883fd</aircraft_seahawk>
|
||||
<aircraft_SeaVixen>21e9817040f8a9ab9160745591915f28</aircraft_SeaVixen>
|
||||
<aircraft_SenecaII>a769ea7ad74deb9a793966b98be001a0</aircraft_SenecaII>
|
||||
<aircraft_sf25b>664ad64136e6958a39b292ec54607037</aircraft_sf25b>
|
||||
<aircraft_sgs233>86308422b554356c850dffb9d0c90b2a</aircraft_sgs233>
|
||||
<aircraft_Short-Stirling>96a0604d6e963d36a35e919f3ca01310</aircraft_Short-Stirling>
|
||||
<aircraft_Short_Empire>868a7faef6fb3bca64a0bcb19b32840c</aircraft_Short_Empire>
|
||||
<aircraft_shuttle>4e24a9c27d36afaec32256a211bef2c3</aircraft_shuttle>
|
||||
<aircraft_SIAI-Marchetti-S.205R>2771caeaa310c1a6970e95c0ea403f3a</aircraft_SIAI-Marchetti-S.205R>
|
||||
<aircraft_SIAI-Marchetti-SF.260>dcab556a830e493703640fd1fdad70eb</aircraft_SIAI-Marchetti-SF.260>
|
||||
<aircraft_Sikorsky-76C>679c00028ac62b9aa3368840147170b5</aircraft_Sikorsky-76C>
|
||||
<aircraft_Sikorsky-S38>3856921a90f947ec2f3e70fa23a1f6ea</aircraft_Sikorsky-S38>
|
||||
<aircraft_Sikorsky-S58>9abb2fc4e373ab4431920fdaf45d8a87</aircraft_Sikorsky-S58>
|
||||
<aircraft_Sky-sportster>d9b9c033f30335a81558a201810f862e</aircraft_Sky-sportster>
|
||||
<aircraft_Skyranger>0a7450c02b7ff3de085087668ba975e7</aircraft_Skyranger>
|
||||
<aircraft_Skyvan>712723a74eaa5f47d905c5938d1ecfa3</aircraft_Skyvan>
|
||||
<aircraft_SM-55>dad894bca78456b5e2ba2e2005d2f29a</aircraft_SM-55>
|
||||
<aircraft_sm79>626844492e56226455fa3a399f41c9e9</aircraft_sm79>
|
||||
<aircraft_snowplow>e9eb491ec0bf4d3ad2c2690b94a9be95</aircraft_snowplow>
|
||||
<aircraft_Socata-ST10>37b95c63434f398743ebbdfd2bee8089</aircraft_Socata-ST10>
|
||||
<aircraft_sopwithCamel>7792f06b71703a39936f75eb1f0f1e05</aircraft_sopwithCamel>
|
||||
<aircraft_SpaceShip-One>d082a2f287fc96ade10753e47cff2977</aircraft_SpaceShip-One>
|
||||
<aircraft_SpaceShuttle>39c46f24941da46177122a83f119e8b7</aircraft_SpaceShuttle>
|
||||
<aircraft_SPAD-VII>f250ae8d2a2b28eb4f736aa28e8f6abf</aircraft_SPAD-VII>
|
||||
<aircraft_Spitfire>ca055bf7c4d39b07a40bb465ad635146</aircraft_Spitfire>
|
||||
<aircraft_spitfireIX>690b3c6a74770738d2d5173fefb48e61</aircraft_spitfireIX>
|
||||
<aircraft_sr20>cbecc0a364fbe6a7aa0c0ea683ce62ea</aircraft_sr20>
|
||||
<aircraft_SR71-BlackBird>29a5495e10aa160cf94b0b9a06e94b48</aircraft_SR71-BlackBird>
|
||||
<aircraft_Stampe-SV4>54ed408f46a6ae86d2b609c58caa2348</aircraft_Stampe-SV4>
|
||||
<aircraft_Starship>078d68204b7b7d11103f97d6067693d2</aircraft_Starship>
|
||||
<aircraft_Stearman>791b0a572eba95a6d0fcfdee605b284e</aircraft_Stearman>
|
||||
<aircraft_Stieglitz>7c5d4939a29bbde445fa5a51a806a600</aircraft_Stieglitz>
|
||||
<aircraft_Stiletto>f469bf3d05e34508c4644c9f21adde9b</aircraft_Stiletto>
|
||||
<aircraft_Storch>987d5891ea899b92697b3dbae69f4290</aircraft_Storch>
|
||||
<aircraft_Su-25>fc53b9f9e774bf455099a41e44f163e0</aircraft_Su-25>
|
||||
<aircraft_SU-37>f0f2e74ef26520d16f11c26adcfa7244</aircraft_SU-37>
|
||||
<aircraft_Submarine_Scout>57853593a2c72148f0de00faa70d67d4</aircraft_Submarine_Scout>
|
||||
<aircraft_Super-Etendard>ea86ee06b4d358790036fe22ae8673a3</aircraft_Super-Etendard>
|
||||
<aircraft_Super-Frelon>92a9c71fb1666816273b3283e7d02504</aircraft_Super-Frelon>
|
||||
<aircraft_superguppySGT>86c50734cf3e657a4bb0646ae4848af3</aircraft_superguppySGT>
|
||||
<aircraft_Supermarine-S.6B>b59d6790040c27853338b680067edc52</aircraft_Supermarine-S.6B>
|
||||
<aircraft_Superwal>92158d7e55f4a892b3d3640cf0b254f0</aircraft_Superwal>
|
||||
<aircraft_T-4>8518cfd8bec8278d0681f67dc7293906</aircraft_T-4>
|
||||
<aircraft_T-50>2e45346a0f377bcb6adc59be3c05d72a</aircraft_T-50>
|
||||
<aircraft_T37>7607a3732fee1ad3b43d44875764afe0</aircraft_T37>
|
||||
<aircraft_T38>1039def0bf9d28ef2cc3a4b5649a9bcb</aircraft_T38>
|
||||
<aircraft_TBM-Avenger>3118e96ceee1f63c4c5f916e48a62e3c</aircraft_TBM-Avenger>
|
||||
<aircraft_Tecnam-P2006T>45daae280d68e757730051ce96933435</aircraft_Tecnam-P2006T>
|
||||
<aircraft_Tecnam-P2010>d27cfef60c88f2785585db762aff50c0</aircraft_Tecnam-P2010>
|
||||
<aircraft_Tecnam-P92>eefbe319cbc34fed4d63ace54f2fc1c8</aircraft_Tecnam-P92>
|
||||
<aircraft_Tigre>806acc4c1616d1d940e61d27737e39f6</aircraft_Tigre>
|
||||
<aircraft_TU-114>f6ce2c5a24ea1545e1d22956017e31b0</aircraft_TU-114>
|
||||
<aircraft_Tu-134>66cee3c0d3e34c4bd97599c1a633c7db</aircraft_Tu-134>
|
||||
<aircraft_TU-95>71c35b11bb1662bd612bc8e3e21232e5</aircraft_TU-95>
|
||||
<aircraft_Tu-SB2bis-M103>50cd266f7a98b7d19ec75b9be804e715</aircraft_Tu-SB2bis-M103>
|
||||
<aircraft_tu154>e5fd32dabb3412be5797805b5b00c002</aircraft_tu154>
|
||||
<aircraft_tu154b>7a7bd91ea1d3c40e3f52a3453f6d5789</aircraft_tu154b>
|
||||
<aircraft_UH-1>0c2692680244c3848e16c5f5cc6e525f</aircraft_UH-1>
|
||||
<aircraft_UH-60>3126bd7f0dc24fb15fbaa6516bbc08d9</aircraft_UH-60>
|
||||
<aircraft_V22-Osprey>1b1eb3803d01ea5dbfaee1836c9efb02</aircraft_V22-Osprey>
|
||||
<aircraft_Velocity-XL>85770badb88a7a876bb828718cc4a30f</aircraft_Velocity-XL>
|
||||
<aircraft_Vickers-Vanguard>1c9f328d29ee7e2453bf30a6b05939f4</aircraft_Vickers-Vanguard>
|
||||
<aircraft_Vickers-Vimy>5d6709607fc95b3867fc491c0fe5e5e3</aircraft_Vickers-Vimy>
|
||||
<aircraft_victor>ee0b3f5284765e02f1357f1cf7071ee1</aircraft_victor>
|
||||
<aircraft_VMX22-Osprey>39f6e98033e45e3b599cdff5b72d7328</aircraft_VMX22-Osprey>
|
||||
<aircraft_Vostok-1>9dc57923ec3e984723338db44460b4fe</aircraft_Vostok-1>
|
||||
<aircraft_vulcanb2>f2eabbfcc31b0ab183fb4b91ba4f19c4</aircraft_vulcanb2>
|
||||
<aircraft_Westland-Whirlwind>cce4ae63928058699f87b61a9604d1b1</aircraft_Westland-Whirlwind>
|
||||
<aircraft_wrightFlyer1903>04d855def138064915a06781720d33cc</aircraft_wrightFlyer1903>
|
||||
<aircraft_X15>a4e382d1493412f3d5cb1e06f9ec9b88</aircraft_X15>
|
||||
<aircraft_x24b>c209d368e99561002a43697c0496d87d</aircraft_x24b>
|
||||
<aircraft_XB-70>749a85a21354df350ddb8c50a5561b22</aircraft_XB-70>
|
||||
<aircraft_XP-67>83cebd2f3cf663215a8bb97dcd38b13e</aircraft_XP-67>
|
||||
<aircraft_Yak-130>b867555c6e06befe0715665c2a10931d</aircraft_Yak-130>
|
||||
<aircraft_Yak-18T>e514c7719ac869a86ff466a22de3554d</aircraft_Yak-18T>
|
||||
<aircraft_Yak-23>c1e1b2a685c99e73720bca83f0c01405</aircraft_Yak-23>
|
||||
<aircraft_Yak-36>2db3c206f581c88c329567013d16aca3</aircraft_Yak-36>
|
||||
<aircraft_yak3>62ff0d85b3b5d71c2854623bcad155cb</aircraft_yak3>
|
||||
<aircraft_YardStik>44106df1f8f1145bb7f9d465a3d85233</aircraft_YardStik>
|
||||
<aircraft_YF-23>bf82709deb10a369d7eaa23d623f631a</aircraft_YF-23>
|
||||
<aircraft_YS-11>f32ab303e103ceeb6ca46926f2c1f510</aircraft_YS-11>
|
||||
<aircraft_ZF_Navy_free_balloon>d6d11bb00006f7b6da2f4939ef06af23</aircraft_ZF_Navy_free_balloon>
|
||||
<aircraft_ZivkoEdge>01893b6c69d97c42f223d95ff8595ff7</aircraft_ZivkoEdge>
|
||||
<aircraft_Zlin-50lx>ec52deb7d44c5186c324ac0532ff2bc8</aircraft_Zlin-50lx>
|
||||
<aircraft_ZLT-NT>60ffdd2bd30dc4a02dfca2ced49bbec5</aircraft_ZLT-NT>
|
||||
<aircraft_IL-76>4a8d5a29427d179a6b0566d79555cbad</aircraft_IL-76>
|
||||
<aircraft_SuperGuepard912>eedc5b614bac903c03dfdd287dc0123a</aircraft_SuperGuepard912>
|
||||
<aircraft_Heinkel-He-111Z>e1f2b5c9d0a65366efd6f4840725d3c5</aircraft_Heinkel-He-111Z>
|
||||
<aircraft_c182s>e307c8d98edfad2432ceea160a5b455d</aircraft_c182s>
|
||||
<aircraft_Cessna-L19>3c40924714e6511a2c7c2e8d64a22e4c</aircraft_Cessna-L19>
|
||||
<aircraft_Boomerang>e9c38c20924902a8cb168d69adf028c5</aircraft_Boomerang>
|
||||
<aircraft_Arsenal-Delanne-10>e01bdd83f13783e98eae4d89d7c55405</aircraft_Arsenal-Delanne-10>
|
||||
</PropertyList>
|
||||
23
catalog/fgaddon-catalog/template.xml
Normal file
23
catalog/fgaddon-catalog/template.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Template catalog - copy and modify for your site as required-->
|
||||
<PropertyList>
|
||||
<template>
|
||||
<version n="0">3.4.*</version>
|
||||
<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>
|
||||
<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>
|
||||
<description>This hangar provides aircraft officially supported and maintained by the FlightGear project, under a free-software license.</description>
|
||||
<de>
|
||||
<description>Auf Deutsch</description>
|
||||
</de>
|
||||
<fr>
|
||||
<description>En Francais</description>
|
||||
</fr>
|
||||
</template>
|
||||
</PropertyList>
|
||||
5
catalog/fgaddon-catalog/zip-excludes.lst
Normal file
5
catalog/fgaddon-catalog/zip-excludes.lst
Normal file
@@ -0,0 +1,5 @@
|
||||
*/.svn/*
|
||||
*.xcf
|
||||
*.blend
|
||||
*.psd
|
||||
*~
|
||||
335
catalog/update-catalog.py
Executable file
335
catalog/update-catalog.py
Executable file
@@ -0,0 +1,335 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import hashlib # md5
|
||||
import lxml.etree as ET
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
CATALOG_VERSION = 4
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--update", help="Update/pull SCM source",
|
||||
action="store_true")
|
||||
parser.add_argument("--no-update",
|
||||
help="Disable updating from SCM source",
|
||||
action="store_true")
|
||||
parser.add_argument("--clean", help="Force regeneration of all zip files",
|
||||
action="store_true")
|
||||
parser.add_argument("dir", help="Catalog directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
# xml node (robust) get text helper
|
||||
def get_xml_text(e):
|
||||
if e != None and e.text != None:
|
||||
return e.text
|
||||
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 ]
|
||||
result = subprocess.check_output( command )
|
||||
match = re.search('Last Changed Date: (\d+)\-(\d+)\-(\d+)', result)
|
||||
if match:
|
||||
rev_str = match.group(1) + match.group(2) + match.group(3)
|
||||
return int(rev_str)
|
||||
|
||||
# find the most recent mtime within a directory subtree
|
||||
def scan_dir_for_change_date_mtime(path):
|
||||
maxsec = 0
|
||||
names = os.listdir(path)
|
||||
for name in names:
|
||||
fullname = os.path.join(path, name)
|
||||
if name == '.' or name == '..':
|
||||
pass
|
||||
elif os.path.isdir( fullname ):
|
||||
mtime = scan_dir_for_change_date_mtime( fullname )
|
||||
if mtime > maxsec:
|
||||
maxsec = mtime
|
||||
else:
|
||||
mtime = os.path.getmtime( fullname )
|
||||
if mtime > maxsec:
|
||||
maxsec = mtime
|
||||
return maxsec
|
||||
|
||||
def make_aircraft_zip(repo_path, name, zip_file):
|
||||
print "Updating:", name + '.zip'
|
||||
savedir = os.getcwd()
|
||||
os.chdir(repo_path)
|
||||
if os.path.exists(zip_file):
|
||||
os.remove(zip_file)
|
||||
command = ['zip', '-rq', '-9']
|
||||
if os.path.exists(zip_excludes):
|
||||
command += ['-x@' + zip_excludes]
|
||||
else:
|
||||
print "warning: no zip-excludes.lst file provided", zip_excludes
|
||||
command += [zip_file, name]
|
||||
subprocess.call(command)
|
||||
os.chdir(savedir)
|
||||
|
||||
def get_md5sum(file):
|
||||
f = open(file, 'r')
|
||||
md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
return md5sum
|
||||
|
||||
#def get_file_stats(file):
|
||||
# f = open(file, 'r')
|
||||
# md5 = hashlib.md5(f.read()).hexdigest()
|
||||
# file_size = os.path.getsize(file)
|
||||
# return (md5, file_size)
|
||||
|
||||
if not os.path.isdir(args.dir):
|
||||
print "A valid catalog directory must be provided"
|
||||
exit(0)
|
||||
|
||||
parser = ET.XMLParser(remove_blank_text=True)
|
||||
|
||||
config_file = os.path.join(args.dir, 'catalog.config.xml')
|
||||
config = ET.parse(config_file, parser)
|
||||
config_node = config.getroot()
|
||||
|
||||
template_file = os.path.join(args.dir, 'template.xml')
|
||||
template = ET.parse(template_file, parser)
|
||||
template_root = template.getroot()
|
||||
template_node = template_root.find('template')
|
||||
|
||||
md5sum_file = os.path.join(args.dir, 'md5sum.xml')
|
||||
if os.path.exists(md5sum_file):
|
||||
md5sum_tree = ET.parse(md5sum_file, parser)
|
||||
md5sum_root = md5sum_tree.getroot()
|
||||
else:
|
||||
md5sum_root = ET.Element('PropertyList')
|
||||
md5sum_tree = ET.ElementTree(md5sum_root)
|
||||
|
||||
scm_list = config_node.findall('scm')
|
||||
upload_node = config_node.find('upload')
|
||||
download_base = get_xml_text(config_node.find('download-url'))
|
||||
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)
|
||||
tmp = os.path.join(args.dir, 'zip-excludes.lst')
|
||||
zip_excludes = os.path.realpath(tmp)
|
||||
|
||||
# freshen repositories
|
||||
if args.no_update:
|
||||
print 'Skipping repository updates.'
|
||||
else:
|
||||
cwd = os.getcwd()
|
||||
for scm in scm_list:
|
||||
repo_type = get_xml_text(scm.find('type'))
|
||||
repo_path = get_xml_text(scm.find('path'))
|
||||
if repo_type == 'svn':
|
||||
print 'SVN update:', repo_path
|
||||
subprocess.call(['svn', 'update', repo_path])
|
||||
elif repo_type == 'git':
|
||||
print 'GIT pull:', repo_path
|
||||
os.chdir(repo_path)
|
||||
subprocess.call(['git','pull'])
|
||||
elif repo_type == 'no-scm':
|
||||
print "No update of unmannaged files:", repo_path
|
||||
else:
|
||||
print "Unknown scm type:", scm, repo_path
|
||||
os.chdir(cwd)
|
||||
|
||||
# names of zip files we want (so we can identify/remove orphans)
|
||||
valid_zips = []
|
||||
|
||||
# create the catalog tree
|
||||
catalog_node = ET.Element('PropertyList')
|
||||
catalog_root = ET.ElementTree(catalog_node)
|
||||
|
||||
# include the template configuration
|
||||
for child in template_node:
|
||||
catalog_node.append(child)
|
||||
|
||||
# scan repositories for catalog information
|
||||
for scm in scm_list:
|
||||
repo_type = get_xml_text(scm.find('type'))
|
||||
repo_path = get_xml_text(scm.find('path'))
|
||||
skip_nodes = scm.findall('skip')
|
||||
skip_list = []
|
||||
for s in skip_nodes:
|
||||
skip_list.append(get_xml_text(s))
|
||||
print 'skip list:', skip_list
|
||||
names = os.listdir(repo_path)
|
||||
for name in sorted(names, key=lambda s: s.lower()):
|
||||
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') )
|
||||
|
||||
# write out the master catalog file
|
||||
cat_file = os.path.join(output_dir, 'catalog.xml')
|
||||
catalog_root.write(cat_file, encoding='utf-8', xml_declaration=True, pretty_print=True)
|
||||
|
||||
# write out the md5sum cache file
|
||||
print md5sum_file
|
||||
md5sum_tree.write(md5sum_file, encoding='utf-8', xml_declaration=True, pretty_print=True)
|
||||
|
||||
# look for orphaned zip files
|
||||
files = os.listdir(output_dir)
|
||||
for file in files:
|
||||
if file.endswith('.zip')and not file in valid_zips:
|
||||
print "orphaned zip:", file
|
||||
|
||||
80
catalogTags.py
Normal file
80
catalogTags.py
Normal file
@@ -0,0 +1,80 @@
|
||||
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
|
||||
80
create_metar_dat.py
Executable file
80
create_metar_dat.py
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# create_metar_dat.py
|
||||
#
|
||||
# Script to create metar.dat.gz by checking tgftp.nws.noaa.gov for stations
|
||||
# that have reported recently.
|
||||
#
|
||||
# Usage: create_metar_dat.py [OUTPUT_FILENAME]
|
||||
#
|
||||
# If OUTPUT_FILENAME is omitted, creates metar.dat.gz in working directory.
|
||||
#
|
||||
# Copyright (c) 2016 Richard Senior
|
||||
#
|
||||
# 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 datetime
|
||||
import dateutil.parser
|
||||
import gzip
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
filename = "metar.dat.gz" if len(sys.argv) <= 1 else sys.argv[1]
|
||||
max_age_days = 7
|
||||
url = "http://tgftp.nws.noaa.gov/data/observations/metar/stations/"
|
||||
|
||||
now = datetime.datetime.now()
|
||||
script = os.path.basename(__file__)
|
||||
|
||||
class ParseException(Exception):
|
||||
pass
|
||||
|
||||
def stations():
|
||||
for line in urllib.request.urlopen(url).readlines():
|
||||
if b".TXT" in line:
|
||||
yield line
|
||||
|
||||
def active_stations():
|
||||
cutoff = now - datetime.timedelta(max_age_days)
|
||||
icao_pattern = re.compile("[A-Z][A-Z0-9]{3}")
|
||||
for station in stations():
|
||||
tokens = station.split()
|
||||
last_modified = tokens[2][14:25]
|
||||
if dateutil.parser.parse(last_modified) > cutoff:
|
||||
icao = tokens[1][16:20:].decode()
|
||||
# Sanity check on parsed ICAO code.
|
||||
if not icao_pattern.match(icao):
|
||||
raise ParseException("Dubious ICAO code: " + icao)
|
||||
yield icao
|
||||
|
||||
# Run through the active stations before opening the file so that a file
|
||||
# is not created (or overwritten) if an exception is thrown.
|
||||
active = [icao + "\n" for icao in active_stations()]
|
||||
|
||||
# Sanity check on the number of stations.
|
||||
if len(active) < 5000:
|
||||
raise ParseException("Expected more than " + str(len(active)) + " stations")
|
||||
|
||||
with gzip.open(filename, "wt") as f:
|
||||
print("# List of airports known to have metar data available", file=f)
|
||||
print("# Generated by", script, "on", now.strftime("%Y-%m-%d"), file=f)
|
||||
print("#", url, file=f)
|
||||
f.writelines(active)
|
||||
|
||||
print(script + ": Wrote", len(active), "stations to", filename)
|
||||
|
||||
1947
download_and_compile.sh
Normal file → Executable file
1947
download_and_compile.sh
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1
fgdata
Submodule
1
fgdata
Submodule
Submodule fgdata added at c16a56a8a1
646
fgdata_checkers.py
Normal file
646
fgdata_checkers.py
Normal file
@@ -0,0 +1,646 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function#defaults to Python 3, but should also work in 2.7
|
||||
"""Functions for checking fgdata for various problems (and one for creating smaller/split versions of it)
|
||||
|
||||
By Rebecca Palmer"""
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
from collections import defaultdict
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
import math
|
||||
import tarfile
|
||||
import tempfile
|
||||
import gzip
|
||||
import shutil
|
||||
import time
|
||||
try:
|
||||
devnull=subprocess.DEVNULL#hide annoying nvcompress messages
|
||||
except (AttributeError,NameError):#pre-3.3 Python
|
||||
devnull=None
|
||||
def path_join(*args):
|
||||
"""Unlike plain os.path.join, this always uses forward slashes, and doesn't add a trailing / if the last component is empty"""
|
||||
return os.path.normpath(os.path.join(*args)).replace('\\','/')
|
||||
def rfilelist(path,exclude_dirs=[]):
|
||||
"""Dict of files/sizes in path, including those in any subdirectories (as relative paths)"""
|
||||
files=defaultdict(int)
|
||||
if not os.path.exists(path):
|
||||
return files
|
||||
dirs=[""]
|
||||
while dirs:
|
||||
cdir=dirs.pop()
|
||||
cdirfiles=os.listdir(path_join(path,cdir))
|
||||
for file in cdirfiles:
|
||||
if os.path.isdir(path_join(path,cdir,file)):
|
||||
if path_join(cdir,file) not in exclude_dirs:
|
||||
dirs.append(path_join(cdir,file))
|
||||
else:
|
||||
files[path_join(cdir,file)]=os.path.getsize(path_join(path,cdir,file))
|
||||
return files
|
||||
def strip_comments(text,comment_types=None,filename=None):
|
||||
"""Remove comments from text
|
||||
Assumes comments don't nest (including different types of comments: will be wrong for e.g. /* aaa // bbb */ will-remove-this in C++ if // are removed first)
|
||||
Doesn't check for being inside a string literal, and doesn't check for line-start * in C /* ... */"""
|
||||
if comment_types is None:
|
||||
if filename is None:
|
||||
raise TypeError("must give either filename or comment_types")
|
||||
if os.path.splitext(filename)[1] in (".xml",".eff"):
|
||||
comment_types=(("<!--","-->",""),)
|
||||
elif os.path.splitext(filename)[1] in (".c",".cpp",".cxx",".h",".hpp",".hxx",".frag",".vert"):
|
||||
comment_types=(("//","\n","\n"),("/*","*/",""))
|
||||
elif os.path.splitext(filename)[1] in (".nas",):
|
||||
comment_types=(("#","\n","\n"),)
|
||||
else:
|
||||
comment_types=[]
|
||||
if type(text) in (bytes,bytearray):
|
||||
comment_types=[[bytes(c,encoding="ascii") for c in ct] for ct in comment_types]
|
||||
for comment_type in comment_types:
|
||||
text=text.split(comment_type[0],maxsplit=1)[0]+comment_type[2].join(s.split(comment_type[1],maxsplit=1)[1] for s in text.split(comment_type[0])[1:] if comment_type[1] in s)
|
||||
return text
|
||||
def files_used(pattern,path,exclude_dirs=[],filelist=None,filetypes=None,relative_path=False):
|
||||
"""Files used by an element matching pattern, in a file in path or filelist"""
|
||||
textures=[]
|
||||
if filelist is None:
|
||||
filelist=rfilelist(path,exclude_dirs).keys()
|
||||
if filetypes is not None:
|
||||
filelist=[f for f in filelist if os.path.splitext(f)[1] in filetypes]
|
||||
texfind=re.compile(pattern)
|
||||
for file in filelist:
|
||||
try:
|
||||
f=open(path_join(path,file),'r',errors='replace')
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
for line in f:
|
||||
tex=texfind.search(line)
|
||||
if tex:
|
||||
if relative_path:
|
||||
textures.append(os.path.normpath(path_join(os.path.dirname(file),tex.group(1).replace('\\','/'))).replace('\\','/'))
|
||||
else:
|
||||
textures.append(os.path.normpath(tex.group(1).replace('\\','/')).replace('\\','/'))
|
||||
return textures
|
||||
def find_unused_textures(basedir,output_lists=True,grep_check=False,output_rsync_rules=False,output_comparison_strips=False, output_removal_commands=False,return_used_noregions=False):
|
||||
"""Checks if any textures are unused (wasting space), and if any textures are only available as .dds (not recommended in the source repository, as it is a lossy-compressed format)
|
||||
|
||||
Set basedir to your fg-root, and enable the kind(s) of output you want:
|
||||
output_lists prints lists of unused textures, and of dds-only textures
|
||||
grep_check checks for possible use outside the normal directories; requires Unix shell and assumes side-by-side fgdata,flightgear,simgear
|
||||
output_rsync_rules prints rsync rules for excluding unused textures from the release flightgear-data. Warning: if you use this, re-run this script regularly, in case they start being used
|
||||
output_comparison_strips creates thumbnail strips, unused_duplicate.png/unused_dds.png/high_low.png, for visually checking whether same-name textures are the same (remove the unused one entirely) or different (move it to Unused); requires imagemagick or graphicsmagick
|
||||
output_removal_commands creates another script, delete_unused_textures.sh, which will remove unused textures when run in a Unix shell"""
|
||||
|
||||
false_positives=set(['buildings-lightmap.png','buildings.png','Credits','Globe/00README.txt', 'Globe/01READMEocean_depth_1png.txt', 'Globe/world.topo.bathy.200407.3x4096x2048.png','Trees/convert.pl','Splash1.png','Splash2.png','Splash3.png','Splash4.png','Splash5.png'])#these either aren't textures, or are used where we don't check; 'unknown.rgb','Terrain/unknown.rgb' are also referenced, but already don't exist
|
||||
used_textures=set(files_used(path=path_join(basedir,'Materials'),pattern=r'<(?:texture|object-mask|tree-texture).*?>(\S+?)</(texture|object-mask|tree-texture)'))|false_positives
|
||||
used_textures_noregions=set(files_used(path=path_join(basedir,'Materials'),exclude_dirs=['regions'],pattern=r'<(?:texture|object-mask|tree-texture).*?>(\S+?)</(texture|object-mask|tree-texture)'))|false_positives#this pattern matches a <texture> (possibly with number), <tree-texture> or <object-mask> element
|
||||
used_effectslow=set(files_used(path=path_join(basedir,'Effects'),pattern=r'image.*?>[\\/]?Textures[\\/](\S+?)</.*?image'))|set(files_used(path=path_join(basedir,'Materials'),pattern=r'<building-(?:texture|lightmap).*?>Textures[\\/](\S+?)</building-(?:texture|lightmap)'))#Effects (<image>), and Materials <building-texture>/<building-lightmap>, explicitly includes the Textures/ or Textures.high/
|
||||
used_effectshigh=set(files_used(path=path_join(basedir,'Effects'),pattern=r'image.*?>[\\/]?Textures.high[\\/](\S+?)</.*?image'))|set(files_used(path=path_join(basedir,'Materials'),pattern=r'<building-(?:texture|lightmap).*?>Textures.high[\\/](\S+?)</building-(?:texture|lightmap)'))
|
||||
high_tsizes=rfilelist(path_join(basedir,'Textures.high'))
|
||||
high_textures=set(high_tsizes.keys())
|
||||
low_tsizes=rfilelist(path_join(basedir,'Textures'),exclude_dirs=['Sky','Unused'])#sky textures are used where we don't check
|
||||
low_textures=set(low_tsizes.keys())
|
||||
only_high=high_textures-low_textures
|
||||
used_noreg_onlyhigh=(only_high&used_textures_noregions)|used_effectshigh
|
||||
used_noreg_onlyhighsize=sum(high_tsizes[t] for t in used_noreg_onlyhigh)
|
||||
used_noreg_low=(low_textures&used_textures_noregions)|used_effectslow
|
||||
used_noregions=used_textures_noregions|used_effectshigh|used_effectslow
|
||||
used_noreg_lowsize=sum(low_tsizes[t] for t in used_noreg_low)
|
||||
used_noreg_defsize=sum(low_tsizes[t] for t in (used_textures_noregions-high_textures)|used_effectslow)+sum(high_tsizes[t] for t in used_textures_noregions|used_effectshigh)
|
||||
used_defsize=sum(low_tsizes[t] for t in (used_textures-high_textures)|used_effectslow)+sum(high_tsizes[t] for t in used_textures|used_effectshigh)
|
||||
unused=(high_textures|low_textures)-used_textures-used_effectslow-used_effectshigh
|
||||
t_size=lambda tset: sum(high_tsizes[t] for t in tset)+sum(low_tsizes[t] for t in tset)
|
||||
missing=(used_textures-(high_textures|low_textures))|(used_effectslow-low_textures)|(used_effectshigh-high_textures)
|
||||
if missing:
|
||||
raise ValueError("Some used textures not found: "+repr(missing))
|
||||
sourceless=[f for f in (high_textures|low_textures) if (f[-4:]==".dds" and f[:-4]+".png" not in high_textures and (f in high_textures or f[:-4]+".png" not in low_textures) )]+['Terrain/airport.dds']#airport.dds isn't the same as airport.png; crop-colors.dds/cropgrass-colors.dds/rock-colors.dds/forest-colors.dds also differ but only in strip width, which doesn't matter as they are 1D color strips
|
||||
sourceless_used=set(sourceless)-unused
|
||||
needed_as_source=[f for f in unused if (f[-4:]!=".dds" and f[:-4]+".png" in (used_textures|used_effectslow|used_effectshigh) or f[:-4]+".dds" in (used_textures|used_effectslow|used_effectshigh))]+['Runway/designation_letters.svg']
|
||||
known_non_duplicates=['deciduous.png','drycrop.png','irrcrop.png','marsh1.png','gravel.png','Town.png','grass.png','mixedcrop.png','resgrid.png']+['glacier.png','rock.png','cropgrass.png']#first group real winter textures, second group unrelated textures
|
||||
unused_duplicate=[f for f in unused if (f[0:14]=="Terrain.winter" and "Terrain"+f[14:] in (high_textures|low_textures) and f[15:] not in known_non_duplicates)]
|
||||
unused_dds=set(f for f in (unused-set(unused_duplicate)) if (f[-4:]==".dds" and f[:-4]+".png" in (high_textures|low_textures) and f!='Terrain/airport.dds'))#airport.dds isn't the same as airport.png; crop-colors.dds/cropgrass-colors.dds/rock-colors.dds/forest-colors.dds also differ but only in strip width, which doesn't matter as they are 1D color strips
|
||||
unused_other=unused-set(unused_duplicate)-set(unused_dds)-set(needed_as_source)
|
||||
known_highlow_mismatch=set(['Terrain.winter/mixedcrop4.png','Terrain.winter/cropgrass3.png','Terrain.winter/drycrop4.png','Terrain.winter/irrcrop2.png','Terrain.winter/drycrop1.png','Terrain.winter/drycrop3.png','Terrain.winter/mixedcrop1.png','Terrain.winter/ mixedforest2.png','Terrain.winter/cropgrass2.png','Terrain.winter/cropgrass1.png','Terrain.winter/tundra.png','Terrain.winter/mixedforest3.png','Terrain.winter/shrub2.png','Terrain.winter/drycrop2.png','Terrain.winter/deciduous1.png','Terrain.winter/ mixedcrop3.png','Terrain.winter/naturalcrop1.png']+['Terrain.winter/tundra3.png','Terrain.winter/forest1c.png','Terrain.winter/herbtundra.png']+['Terrain/grass_rwy.dds','Terrain/cropwood.dds','Terrain/herbtundra.dds','Terrain/irrcrop.dds','Terrain/shrub.dds','Terrain.winter/mixedforest.png','Runway/pa_taxiway.png','Runway/pc_taxiway.png'])#first group are different degrees of snow cover on the same base texture, last group unrelated textures, middle group hard to tell; p{a,c}_taxiway (only low-res has side lines) are also mismatched in .dds, but as each .dds matches its size .png, only the .png needs to be kept in Unused
|
||||
lowres_maybe_source=['Terrain/lava1.png','Terrain/lava2.png','Terrain/lava3.png','Terrain/sand4.png','Terrain/sand5.png','Terrain/sand6.png']#these are clearly related, but the high-res version has unnatural-looking high-frequency noise, suggesting that the low-res version might be the original: keep it
|
||||
unused_dds_matchhigh=set(f for f in (unused_dds&known_highlow_mismatch) if f[:-4]+".png" not in low_textures)
|
||||
unused_dds_matchlow=set(f for f in (unused_dds&known_highlow_mismatch) if f[:-4]+".png" not in high_textures)
|
||||
low_unneeded=(high_textures&low_textures)-used_effectslow-unused-set(lowres_maybe_source)
|
||||
low_unneeded_duplicate=low_unneeded-set(known_highlow_mismatch)
|
||||
low_unneeded_nondup=low_unneeded&set(known_highlow_mismatch)
|
||||
def image_check_strip(basedir,index_fname,ilist1,ilist2=None,size=128):
|
||||
"""Generate two rows of thumbnails, for easy visual comparison (between the two lists given, or if a single list is given, between low and high resolution)"""
|
||||
if not ilist1:
|
||||
print(index_fname," empty, skipping")
|
||||
return
|
||||
if ilist2 is None:
|
||||
ipairs=[[path_join(basedir,'Textures',f),path_join(basedir,'Textures.high',f)] for f in ilist1]
|
||||
else:
|
||||
ipairs=[]
|
||||
for f1,f2 in zip(ilist1,ilist2):
|
||||
if f1 in low_textures:
|
||||
ipairs.append([path_join(basedir,'Textures',f1),path_join(basedir,'Textures',f2) if f2 in low_textures else path_join(basedir,'Textures.high',f2)])
|
||||
if f1 in high_textures:
|
||||
ipairs.append([path_join(basedir,'Textures.high',f1),path_join(basedir,'Textures.high',f2) if f2 in high_textures else path_join(basedir,'Textures',f2)])
|
||||
ilist_f=[f[0] for f in ipairs]+[f[1] for f in ipairs]
|
||||
subprocess.call(['montage','-label',"'%f'"]+ilist_f+['-tile','x2','-geometry',str(size)+'x'+str(size)]+[index_fname])
|
||||
def rsync_rules(basedir,flist,include=False,high=None):
|
||||
"""Output rsync rules to exclude/include the specified textures from high/low/both (high=True/False/None) resolutions"""
|
||||
for f in flist:
|
||||
if high!=True and f in low_textures:
|
||||
print("+" if include else "-",path_join('/fgdata/Textures',f))
|
||||
if high!=False and f in high_textures:
|
||||
print("+" if include else "-",path_join('/fgdata/Textures.high',f))
|
||||
def removal_command(basedir,flist,high=None):
|
||||
"""Return command to delete the specified textures from high/low/both (high=True/False/None) resolutions"""
|
||||
if not flist:
|
||||
return ""
|
||||
a="rm"
|
||||
for f in flist:
|
||||
if high!=True and f in low_textures:
|
||||
a=a+" "+path_join('Textures',f)
|
||||
if high!=False and f in high_textures:
|
||||
a=a+" "+path_join('Textures.high',f)
|
||||
a=a+"\n"
|
||||
return a
|
||||
def move_command(basedir,flist,high=None,comment=False):
|
||||
"""Return command to move the specified textures to Unused from high/low/both (high=True/False/None) resolutions"""
|
||||
if not flist:
|
||||
return ""
|
||||
dirset_low=set() if high==True else set(os.path.dirname(f) for f in set(flist)&low_textures)
|
||||
dirset_high=set() if high==False else set(os.path.dirname(f) for f in set(flist)&high_textures)
|
||||
a=""
|
||||
for d in dirset_low:
|
||||
a=a+("#" if comment else "")+"mv --target-directory="+path_join("Textures/Unused",d)+" "+(" ".join(path_join("Textures",f) for f in flist if (os.path.dirname(f)==d and f in low_textures)))+"\n"
|
||||
for d in dirset_high:
|
||||
a=a+("#" if comment else "")+"mv --target-directory="+path_join("Textures/Unused",d+".high")+" "+(" ".join(path_join("Textures.high",f) for f in flist if (os.path.dirname(f)==d and f in high_textures)))+"\n"
|
||||
return a
|
||||
if output_comparison_strips:
|
||||
image_check_strip(basedir,"unused_duplicate.png",unused_duplicate,["Terrain"+f[14:] for f in unused_duplicate])
|
||||
image_check_strip(basedir,"unused_dds.png",unused_dds,[f[:-4]+".png" for f in unused_dds])
|
||||
dds_skip=set(['Runway/rwy-normalmap.dds','Water/perlin-noise-nm.dds','Water/water_sine_nmap.dds','Water/waves-ver10-nm.dds'])
|
||||
used_dds_withpng=set(f for f in (high_textures|low_textures) if (f[-4:]==".dds" and f[:-4]+".png" in (high_textures|low_textures)))-unused_dds-dds_skip
|
||||
print(".dds omitted from comparison strip (normal maps etc): ",dds_skip)
|
||||
#used_dds_withpng different: p{a,c}_taxiway.dds and possibly more runway markings (darker),sand{4,5,6}.dds(less high-freq noise),water.dds(more high-freq noise),grass_rwy.dds (has stripes),cropwood.dds,irrcrop.dds,shrub.dds,herbtundra.dds,cropgrass.dds(unrelated)
|
||||
#water-reflection.{png,dds} really are plain white (so do match), not an alpha map
|
||||
image_check_strip(basedir,"used_dds.png",used_dds_withpng,[f[:-4]+".png" for f in used_dds_withpng])
|
||||
image_check_strip(basedir,"high_low.png",high_textures&low_textures)
|
||||
#image_check_strip(basedir,"high_low2.png",[f for f in high_textures&low_textures if (f[0:14]=="Terrain.winter" or "_taxiway." in f or "lava" in f or "sand" in f)],size=512)#closer look at the doubtful cases
|
||||
if output_lists:
|
||||
print("\n\nunused-winter same as normal:",sorted(unused_duplicate),"\nsize=",t_size(unused_duplicate),"\n\nunused-dds with matching png:",sorted(unused_dds),"\nsize=",t_size(unused_dds),"\n\nunused-unique:",sorted(unused_other),"\nsize=",t_size(unused_other),"\n\nnot directly used but keep as source:",sorted(needed_as_source),"\nsize=",t_size(needed_as_source),"\n\nunused low, matches high:",sorted(low_unneeded_duplicate),"\nsize=",sum(low_tsizes[f] for f in low_unneeded_duplicate),"\n\nunused low, unique:",sorted(low_unneeded_nondup),"\nsize=",sum(low_tsizes[f] for f in low_unneeded_nondup),"\n\nall non-sky textures size=",sum(high_tsizes.values())+sum(low_tsizes.values()),"used size=",used_defsize,"used no-regions size=",used_noreg_defsize,"\n\nnot found:",sorted(missing),"\n\n.dds only/highest-res:",sorted(sourceless),"\n\n.dds only/highest-res, used:",sorted(sourceless_used))
|
||||
#not really meaningful after removing low-res duplicates: ,"\n\nused high-only, not regions:",sorted(used_noreg_onlyhigh),"\nsize=",used_noreg_onlyhighsize,"these+used low (i.e. minimal flightgear-data) size=",used_noreg_onlyhighsize+used_noreg_lowsize
|
||||
if grep_check:
|
||||
unused_f=[os.path.basename(f) for f in unused]
|
||||
all_f=[os.path.basename(f) for f in (high_textures|low_textures)]
|
||||
print("\n\nPossible use outside main search:")#used to set false_positives
|
||||
subprocess.call(["grep","-r","-E","--exclude-dir=Aircraft","--exclude-dir=.git","-e","("+")|(".join(unused)+")",basedir,path_join(basedir,"../flightgear"),path_join(basedir,"../simgear")])#everywhere using full names
|
||||
subprocess.call(["grep","-r","-E","--exclude-dir=Aircraft","--exclude-dir=Textures.high","--exclude-dir=Models","--exclude-dir=Materials","--exclude-dir=Effects","--exclude-dir=.git","-e","("+")|(".join(all_f)+")",basedir,path_join(basedir,"../flightgear"),path_join(basedir,"../simgear")])#restricted (to avoid false positives from Terrain.winter vs Terrain) using filenames
|
||||
subprocess.call(["grep","-r","-E","--exclude-dir=Aircraft","--exclude-dir=Textures.high","--exclude-dir=Models","--exclude-dir=Materials","--exclude-dir=Effects","--exclude-dir=.git","-e",'[."\']dds',basedir,path_join(basedir,"../flightgear"),path_join(basedir,"../simgear")])#check for programmatic .png -> .dds swap; none found
|
||||
print("\n\nUse of sourceless textures:")
|
||||
subprocess.call(["grep","-r","-E","--exclude-dir=Aircraft","--exclude-dir=.git","-e","("+")|(".join(sourceless)+")",basedir,path_join(basedir,"../flightgear"),path_join(basedir,"../simgear")])
|
||||
if output_rsync_rules:
|
||||
print("\n\nFull flightgear-data:\n")
|
||||
rsync_rules(basedir,unused)
|
||||
rsync_rules(basedir,low_unneeded,high=False)
|
||||
print("\n\nMinimal flightgear-data:\n")
|
||||
rsync_rules(basedir,low_textures-used_noreg_low,high=False)
|
||||
rsync_rules(basedir,high_textures-used_noreg_onlyhigh,high=True)
|
||||
if output_removal_commands:
|
||||
r_script=open('delete_unused_textures.sh','w')
|
||||
r_script.write("cd "+basedir+"\n")
|
||||
r_script.write("#Unused duplicates\n")
|
||||
r_script.write(removal_command(basedir,unused_duplicate))
|
||||
r_script.write("#Unused .dds versions\n")
|
||||
r_script.write(removal_command(basedir,unused_dds-unused_dds_matchhigh,high=False))
|
||||
r_script.write(removal_command(basedir,unused_dds-unused_dds_matchlow,high=True))
|
||||
r_script.write("#Unused reduced-resolution versions\n")
|
||||
r_script.write(removal_command(basedir,low_unneeded_duplicate|(unused_other&high_textures&low_textures)-set(lowres_maybe_source),high=False))
|
||||
r_script.write("#Unused unique .png (move to Unused)\n")
|
||||
r_script.write("\n".join(["mkdir -p Textures/Unused/"+d for d in ['Terrain','Terrain.winter','Trees','Terrain.high','Terrain.winter.high','Trees.high','Runway','Water']])+"\n")
|
||||
r_script.write(move_command(basedir,[f for f in unused_other&high_textures if (f[-4:]!=".dds" and f[:5]!="Signs" and f[:6]!="Runway")],high=True))
|
||||
r_script.write(move_command(basedir,[f for f in (unused_other-high_textures)|low_unneeded_nondup if (f[-4:]!=".dds" and f[:5]!="Signs" and f[:6]!="Runway")],high=False))
|
||||
r_script.write("#Unused unique .dds\n")
|
||||
r_script.write("#It is my opinion that these should go, but if you'd prefer to move them to Unused I won't argue further\n")
|
||||
r_script.write(removal_command(basedir,[f for f in (unused_other&high_textures)|unused_dds_matchlow if (f[-4:]==".dds" and f[:5]!="Signs" and f[:6]!="Runway")],high=True))
|
||||
r_script.write(removal_command(basedir,[f for f in (unused_other-high_textures)|low_unneeded_nondup|unused_dds_matchhigh if f[-4:]==".dds"],high=False))
|
||||
r_script.write(move_command(basedir,[f for f in (unused_other&high_textures)|unused_dds_matchlow if (f[-4:]==".dds" and f[:5]!="Signs" and f[:6]!="Runway")],high=True,comment=True))
|
||||
r_script.write(move_command(basedir,[f for f in (unused_other-high_textures)|low_unneeded_nondup|unused_dds_matchhigh if (f[-4:]==".dds" and f[:5]!="Signs" and f[:6]!="Runway")],high=False,comment=True))
|
||||
r_script.close()
|
||||
if return_used_noregions:
|
||||
return used_noregions|set([path_join('Sky',f) for f in rfilelist(path_join(basedir,'Textures/Sky'))])
|
||||
def find_locally_unused_models(basedir):
|
||||
"""Find models not used in the base scenery (these do need to be in Terrasync as they may well be used in other locations, but don't need to be in the base flightgear-data package)
|
||||
Known bug: doesn't search everywhere: check /Nasal,.eff <image>,<inherits-from>,/(AI/)Aircraft not referenced in AI scenarios, unusual tags in Aircraft/Generic/Human/Models/walker.xml,HLA/av-aircraft.xml,/Environment,MP/aircraft_types.xml,preferences.xml"""
|
||||
models_allfiles={path_join('Models',f):s for f,s in rfilelist(path_join(basedir,'Models')).items()}
|
||||
t_size=lambda flist: sum(models_allfiles[f] for f in flist if f in models_allfiles)
|
||||
used_models=set(files_used(path=path_join(basedir,'Scenery'),filetypes=".stg",pattern=r'OBJECT_SHARED (\S+?) '))|set(files_used(path=path_join(basedir,'AI'),exclude_dirs=["Aircraft","Traffic"],pattern=r'<model>[\\/]?(\S+?)</model>'))|set(f for f in files_used(path=path_join(basedir,'Materials'),filetypes=".xml",pattern=r'<path>[\\/]?(\S+?)</path>') if f[-4:]==".xml")
|
||||
n=0
|
||||
while n!=len(used_models):
|
||||
n=len(used_models)
|
||||
used_models=used_models|set(f for f in files_used(path=basedir,filelist=used_models,filetypes=".xml",pattern=r'<path>[\\/]?(\S+?)</path>') if f[-4:]==".xml")
|
||||
used_textures=set(files_used(path=basedir,filelist=used_models,filetypes=".ac",pattern=r'texture "(\S+?)"',relative_path=True))|set(files_used(path=basedir,filelist=used_models,filetypes=".xml",pattern=r'<texture>[\\/]?(\S+?)</texture>',relative_path=True))
|
||||
extra_used_models=set()
|
||||
for f1 in used_models:
|
||||
if f1[-4:]!=".xml":
|
||||
continue
|
||||
for f2 in files_used(path=basedir,filelist=[f1],pattern=r'<path>[\\/]?(\S+?)</path>',relative_path=True):
|
||||
if f2[-3:]!=".ac":
|
||||
continue
|
||||
extra_used_models=extra_used_models|set([f2])
|
||||
p2=[f for f in files_used(path=basedir,filelist=[f1],pattern=r'<texture-path>[\\/]?(\S+?)</texture-path>',relative_path=True)]
|
||||
if len(p2)==0:
|
||||
p2=[os.path.dirname(f1)]
|
||||
if len(p2)!=1:
|
||||
print("non-unique/not found:",f1,f2,p2)
|
||||
continue
|
||||
try:
|
||||
used_textures=used_textures|set(os.path.normpath(path_join(p2[0],f)) for f in files_used(path=basedir,filelist=[f2],filetypes=".ac",pattern=r'texture "(\S+?)"'))
|
||||
except (IOError,OSError):
|
||||
print("not found",f1,f2,p2)
|
||||
used_models=used_models|extra_used_models
|
||||
unused=set(models_allfiles.keys())-(used_models|used_textures)
|
||||
missing=set(f for f in (used_models|used_textures) if ((f.startswith('Models') and f not in models_allfiles.keys()) or not os.path.isfile(path_join(basedir,f))))
|
||||
print("used\n",sorted(used_models),"\nsize=",t_size(used_models),"\n\n",sorted(used_textures),"\nsize=",t_size(used_textures),"\n\nunused\n",sorted(unused),"\nsize=",t_size(unused),"\n\nmissing\n",sorted(missing),"\nsize=",t_size(missing))
|
||||
|
||||
class FilesetSizes:
|
||||
def __init__(self):
|
||||
self.count=0
|
||||
self.ncsize=0
|
||||
self.csize=0
|
||||
@property
|
||||
def size(self):
|
||||
if self.csize>0:
|
||||
return self.csize
|
||||
else:
|
||||
return self.ncsize
|
||||
def __str__(self):
|
||||
if self.csize>0:
|
||||
return "{0:10,} {1:15,} {2:15,}".format(self.count,self.ncsize,self.csize)
|
||||
else:
|
||||
return "{0:10,} {1:15,}".format(self.count,self.ncsize)
|
||||
def __add__(self,other):
|
||||
result=FilesetSizes()
|
||||
result.count=self.count+other.count
|
||||
result.ncsize=self.ncsize+other.ncsize
|
||||
result.csize=self.csize+other.csize
|
||||
return result
|
||||
def size_by_category(path,exclude_dirs,keyfn,compressed_size=False):
|
||||
"""Total size of files, in each category returned from keyfn"""
|
||||
files=rfilelist(path,exclude_dirs)
|
||||
result=defaultdict(FilesetSizes)
|
||||
gzdir=tempfile.TemporaryDirectory()
|
||||
gzpath=gzdir.name
|
||||
gzcount=0
|
||||
for file,size in files.items():
|
||||
cat=keyfn(file,size)
|
||||
if cat is None:
|
||||
continue
|
||||
result[cat].count=result[cat].count+1
|
||||
result[cat].ncsize=result[cat].ncsize+size
|
||||
if compressed_size:
|
||||
try:
|
||||
result[cat].targz.add(path_join(path,file))
|
||||
except AttributeError:
|
||||
result[cat].targzname=path_join(gzpath,str(gzcount)+".tar.gz")
|
||||
result[cat].targz=tarfile.open(result[cat].targzname,mode="w:gz")
|
||||
gzcount=gzcount+1
|
||||
result[cat].targz.add(path_join(path,file))
|
||||
if compressed_size:
|
||||
for cat in result:
|
||||
result[cat].targz.close()
|
||||
result[cat].csize=os.path.getsize(result[cat].targzname)
|
||||
return result
|
||||
def fgdata_size(path,by_size=False,exclude_dirs=None,compressed_size=False,min_size=1e6,include_aircraft=['UIUC','777','777-200','b1900d','CitationX','ZLT-NT','dhc2','Cub','sopwithCamel','f-14b','ASK13','bo105','Dragonfly','SenecaII','A6M2'],sections={"Aircraft/c172p":"Aircraft-base","Aircraft/Generic":"Aircraft-base","Aircraft/Instruments":"Aircraft-base","Aircraft/Instruments-3d":"Aircraft-base","Aircraft/ufo":"Aircraft-base","Aircraft/777":"Aircraft-777","Aircraft/777-200":"Aircraft-777","Aircraft":"Aircraft-other","Textures":"Textures","Textures.high":"Textures","AI/Aircraft":"AI-aircraft","AI":"AI-other","Scenery":"scenery","Models":"models"}):
|
||||
if any('\\' in s for s in sections):
|
||||
raise ValueError("sections always uses forward slashes")
|
||||
if "" not in sections:
|
||||
sections[""]="Other"
|
||||
if exclude_dirs is None:
|
||||
if os.path.exists(path_join(path,".git")):
|
||||
exclude_dirs=[".git","Textures/Unused"]+[path_join("Aircraft",d) for d in os.listdir(path_join(path,"Aircraft")) if d not in ["c172p","ufo","Generic","Instruments","Instruments-3d"]+include_aircraft]
|
||||
else:
|
||||
exclude_dirs=[]
|
||||
if by_size:
|
||||
keyfn=lambda file,size: ("texture",math.frexp(size)[1]) if os.path.splitext(file)[1] in [".png",".dds",".rgb",".jpg"] else ("nontexture",math.frexp(size)[1])
|
||||
else:
|
||||
def keyfn(file,size):
|
||||
file_ext=os.path.splitext(file)[1]
|
||||
if file_ext==".gz":
|
||||
file_ext=os.path.splitext(os.path.splitext(file)[0])[1]+file_ext
|
||||
file0=file.replace('\\','/')
|
||||
section=sections[max((s for s in sections if file0.startswith(s)),key=len)]
|
||||
return (section,file_ext)
|
||||
result=size_by_category(path,exclude_dirs,keyfn,compressed_size)
|
||||
#print(result)
|
||||
totals1=defaultdict(FilesetSizes)
|
||||
totals2=defaultdict(FilesetSizes)
|
||||
other=defaultdict(FilesetSizes)
|
||||
for cat in result:
|
||||
totals1[cat[0]]=totals1[cat[0]]+result[cat]
|
||||
totals2[cat[1]]=totals2[cat[1]]+result[cat]
|
||||
if (not by_size) and (result[cat].size<min_size):
|
||||
other[cat[0]]=other[cat[0]]+result[cat]
|
||||
print("{0:>10} {1:>15} {2:>15}".format("Count","Size","Compr.size"))
|
||||
for cat0,r0 in sorted(totals1.items(),key=lambda p:-p[1].size):
|
||||
print(cat0)
|
||||
for cat,r in sorted([(c[1],r) for (c,r) in result.items() if (c[0]==cat0 and (by_size or r.size>min_size))],key=(lambda p:p[0]) if by_size else (lambda p:-p[1].size)):
|
||||
print(r,cat)
|
||||
if not by_size:
|
||||
print(other[cat0],"other")
|
||||
print(totals1[cat0],"all")
|
||||
print("All")
|
||||
for cat,r in sorted([(c,r) for (c,r) in totals2.items() if (by_size or r.size>min_size)],key=(lambda p:p[0]) if by_size else (lambda p:-p[1].size)):
|
||||
print(r,cat)
|
||||
if not by_size:
|
||||
print(sum((r for r in totals2.values() if r.size<min_size),FilesetSizes()),"other")
|
||||
print(sum(totals1.values(),FilesetSizes()),"all")
|
||||
def create_reduced_file(input_path,output_path,temp_path,cdir,file,downsample_this,compress_this,compress_names_find, compressed_format,texture_filetypes,binary_types,fclass):
|
||||
"""Process a single file in create_reduced_fgdata. (Separate function to allow parallel processing)"""
|
||||
retcode=0
|
||||
if downsample_this or compress_this:
|
||||
image_type=texture_filetypes[os.path.splitext(file)[1]]
|
||||
output_image_type=compressed_format if compress_this else os.path.splitext(file)[1]
|
||||
output_file=os.path.splitext(file)[0]+output_image_type
|
||||
output_image_type=texture_filetypes[output_image_type]
|
||||
if "{0}" in output_path and fclass=="base-textures":#downsampled in base-textures, full resolution in extra-textures
|
||||
shutil.copy(path_join(input_path,cdir,file),path_join(output_path.format("extra-textures"),cdir,file))
|
||||
if output_image_type=="DDS":# in Ubuntu, neither imagemagick nor graphicsmagick can write .dds
|
||||
#doesn't work (for dds -> smaller dds): subprocess.call(["nvzoom","-s","0.5","-f","box",path_join(input_path,cdir,file),path_join(output_path.format(fclass),cdir,file)])
|
||||
if subprocess.call(["convert",image_type+":"+path_join(input_path,cdir,file)]+(["-flip"] if ((image_type=="DDS")!=(output_image_type=="DDS")) else [])+(["-sample","50%"] if downsample_this else [])+[path_join(temp_path,cdir,os.path.splitext(file)[0]+".png")]):#fails on some DDS formats, so just copy them
|
||||
shutil.copy(path_join(input_path,cdir,file),path_join(output_path.format(fclass),cdir,file))
|
||||
print(path_join(cdir,file),"unsupported type, probably normal map")
|
||||
if compress_this:
|
||||
raise TypeError#copy will have the wrong name
|
||||
else:
|
||||
try:
|
||||
image_properties=subprocess.check_output(["identify","-verbose",path_join(temp_path,cdir,os.path.splitext(file)[0]+".png")])
|
||||
except subprocess.CalledProcessError as err:
|
||||
print("identify error on",path_join(cdir,file),"after ",["convert",image_type+":"+path_join(input_path,cdir,file)]+(["-flip"] if ((image_type=="DDS")!=(output_image_type=="DDS")) else [])+(["-sample","50%"] if downsample_this else [])+[path_join(temp_path,cdir,os.path.splitext(file)[0]+".png")],["identify","-verbose",path_join(temp_path,cdir,os.path.splitext(file)[0]+".png")],err)
|
||||
raise
|
||||
has_alpha=b"Alpha" in image_properties
|
||||
needs_alpha=has_alpha
|
||||
if has_alpha and re.search(rb"Alpha:\s*min: 255 \(1\)",image_properties):
|
||||
print(path_join(cdir,file),"has always-255 alpha")
|
||||
needs_alpha=False
|
||||
retcode=subprocess.call(["nvcompress","-bc3" if needs_alpha else "-bc1",path_join(temp_path,cdir,os.path.splitext(file)[0]+".png"),path_join(output_path.format(fclass),cdir,output_file)],stdout=devnull)
|
||||
else:
|
||||
retcode=subprocess.call(["convert",image_type+":"+path_join(input_path,cdir,file)]+(["-sample","50%"] if downsample_this else [])+[output_image_type+":"+path_join(output_path.format(fclass),cdir,output_file)])#we use sample rather than an averaging filter to not break mask/rotation/... maps
|
||||
else:#not to be downsampled/compressed
|
||||
if os.path.splitext(file)[1] in binary_types:#just copy
|
||||
shutil.copy(path_join(input_path,cdir,file),path_join(output_path.format(fclass),cdir,file))
|
||||
else:#texture name replacement
|
||||
file_in=open(path_join(input_path,cdir,file),'rb')
|
||||
file_out=open(path_join(output_path.format(fclass),cdir,file),'wb')
|
||||
file_str=file_in.read(None)
|
||||
file_in.close()
|
||||
(file_strout,num_matches)=compress_names_find.subn(lambda mf: os.path.splitext(mf.group(0))[0]+(compressed_format.encode('utf-8')),file_str)
|
||||
file_out.write(file_strout)
|
||||
file_out.close()
|
||||
#if ((os.path.splitext(file)[1] not in textureuser_types) and num_matches>0):
|
||||
#print("Warning: ",num_matches," unexpected use(s) in ",path_join(cdir,file))
|
||||
#if compress_names_find0.search(file_strout):
|
||||
#print("Warning: unreplaced match(es) in ",path_join(cdir,file),compress_names_find0.search(file_strout).group(0))
|
||||
"""Warning: unreplaced match(es) in... correct rejections of match within a filename:
|
||||
Aircraft/Instruments-3d/AN-APS-13.ac b'panel.png'
|
||||
Aircraft/Instruments-3d/magneto-switch/mag_switch.ac b'black.png'
|
||||
Nasal/canvas/map/Images/chart_symbols.svg b'wash.png'
|
||||
Models/Airport/blast-deflector49m.ac b'generic.png'
|
||||
Models/Airport/blast-deflector63m.ac b'generic.png'
|
||||
Models/Industrial/oilrig09.ac b'yellow.png'
|
||||
Models/Industrial/oilrig10.ac b'yellow.png'
|
||||
Models/Industrial/oilrig09.ac.before-color-change b'yellow.png'
|
||||
Models/Industrial/oilrig10.ac.before-color-change b'yellow.png'
|
||||
Models/Maritime/Civilian/Tanker.ac b'black.png'
|
||||
Models/Transport/flatcar.xml b'evergreen.png'
|
||||
Models/Commercial/tower-grey-black.ac b'black.png'
|
||||
Materials/base/materials-base.xml b'yellow.png'
|
||||
|
||||
Warning: unexpected use(s) in...
|
||||
Docs/README.local_weather.html (the only one that looke like an actual problem; hence, Docs is now skipped)
|
||||
Nasal/canvas/map/Images/chart_symbols.svg (probably inkscape:export-filename, which are creator-specific absolute paths anyway, but now skipped)
|
||||
oilrig09.ac.before-color-change,oilrig10.ac.before-color-change,stbd_coaming_panel.ac.bak (presumably backup files)
|
||||
"""
|
||||
if retcode:
|
||||
print("Error ",retcode," in ",path_join(cdir,file))
|
||||
|
||||
def create_reduced_fgdata(input_path,output_path,reject_positional_args=None,split_textures=False,exclude_parts=[],include_aircraft=['UIUC','777','777-200','b1900d','CitationX','ZLT-NT','dhc2','Cub','sopwithCamel','f-14b','ASK13','bo105','Dragonfly','SenecaII','A6M2'],dirs_to_downsample=(),dirs_to_compress=(),compressed_format=".dds",downsample_min_filesize=1e5,compress_min_filesize=3e4,use_ready_compressed=True):
|
||||
"""Create a smaller, reduced-quality flightgear-data package
|
||||
Can downsample textures 50%, change texture format, and/or omit sections (region-specific textures, aircraft, AI traffic)
|
||||
Downsampling and format change require imagemagick or graphicsmagick (for convert) and libnvtt-bin (for nvcompress)
|
||||
|
||||
Optional parts, use exclude_parts to omit:
|
||||
ai: no background traffic, but tankers etc do still work
|
||||
extra-textures (requires split_textures=True): no region-specific textures
|
||||
|
||||
The c172p and ufo are always included; other aircraft are added by include_aircraft
|
||||
|
||||
Texture downsampling: textures in dirs_to_downsample and larger than downsample_min_filesize downsampled 50%
|
||||
Texture format conversion: textures in dirs_to_compress and larger than compress_min_filesize converted to compressed_format
|
||||
use_ready_compressed determines what happens if a same-basename file in compressed_format already exists: True uses the already-compressed one, False uses the uncompressed one, None keeps both
|
||||
Suggested dirs_to_downsample:
|
||||
3.2: ('Textures.high/Terrain','Textures.high/Trees','Textures.high/Terrain.winter','AI/Aircraft','Models')
|
||||
3.3: ('Textures/Terrain','Textures/Trees','Textures/Terrain.winter','AI/Aircraft','Models')
|
||||
To do "everything" (a few are always skipped due to potential breakage), use dirs_to_compress=('',)
|
||||
|
||||
To put each section in its own directory (e.g. for building a Debian-style flightgear-data-* set of packages) use {0} in output_path, e.g.
|
||||
python3 -c "import fgdata_checkers; fgdata_checkers.create_reduced_fgdata(input_path='/home/rnpalmer/fs_dev/git/fgdata',output_path='/home/rnpalmer/fs_dev/flightgear/data_split/debian/flightgear-data-{0}/usr/share/games/flightgear',include_aircraft=['UIUC','b1900d','CitationX','ZLT-NT','dhc2','Cub','sopwithCamel','f-14b','ASK13','bo105','Dragonfly','SenecaII','A6M2'])"
|
||||
This creates separate preferences-regions.xml and preferences-noregions.xml files for with and without regional textures; you need to handle symlinking preferences.xml to the correct one
|
||||
"""
|
||||
start_time=time.time()
|
||||
if reject_positional_args is not None:
|
||||
raise TypeError("Keyword arguments only please: this is not a stable API")
|
||||
if use_ready_compressed not in (True,False,None):
|
||||
raise TypeError("invalid use_ready_compressed setting")
|
||||
texture_filetypes={".png":"PNG",".dds":"DDS",".jpg":"JPEG"}#,".rgb":"SGI" loses cloud transparency
|
||||
if compressed_format not in texture_filetypes:
|
||||
raise ValueError("Invalid compressed_format (include the .)")
|
||||
textureuser_types={".eff",".xml",".ac",".nas"}
|
||||
binary_types={".png",".dds",".rgb",".RGB",".jpg",".wav",".WAV",".btg.gz",".zip",".tar.gz"}#don't search these for texture name replacement
|
||||
"""Textures named directly in flightgear/simgear code:
|
||||
gui/images/shadow.png,gui/cursor-spin-cw.png (probably safest to treat this as gui/*, they're all small)
|
||||
Textures/Globe/world.topo.bathy.200407.3x4096x2048.png
|
||||
Textures/buildings.png,Textures/buildings-lightmap.png
|
||||
Textures/Sky/*
|
||||
Textures/Splash*.png
|
||||
unknown.rgb (probably Textures/ or Textures/Terrain/, neither exists)
|
||||
Aircraft/Instruments/Textures/nd-symbols.png (doesn't actually exist),Aircraft/Instruments/Textures/compass-ribbon.rgb,Aircraft/Instruments/Textures/od_wxradar.rgb,Aircraft/Instruments/Textures/od_wxradar.rgb,Aircraft/Instruments/Textures/wxecho.rgb,Aircraft/Instruments/Textures/od_groundradar.rgb (doesn't actually exist)
|
||||
also, Aircraft/{Instruments,Instruments-3d,Generic} may be used by downloaded aircraft, and Docs images are used in .html
|
||||
Nasal (Canvas map) probably wouldn't break anything, but guessing it's a bad idea visually"""
|
||||
no_compress_pattern=re.compile(r'mask|light|relief|nmap|nm\.|normal|dudv|^Splash[0-9].png$|^buildings.png$|^buildings-lightmap.png$|^world.topo.bathy.200407.3x4096x2048.png$|^ocean_depth_1.png$')#edge blurring from lossy compression may break masks (converting ocean_depth_1.png is known to give black water near shore at effects>=4), and this script doesn't know how to create DDS normal maps
|
||||
no_compress_dirs=("gui","Docs","webgui","Nasal","Textures/Sky","Aircraft/Instruments","Aircraft/Instruments-3d","Aircraft/Generic")
|
||||
exclude_dirs=[".git","Textures/Unused"]
|
||||
exclude_unnamed_subdirs=["Aircraft"]#these are a separate mechanism from subtree_class/exclude_parts mostly to save time (subtree_class still fully scans excluded directories because the class may change again further down the tree, e.g. AI/Aircraft ai -> performancedb.xml base; these don't)
|
||||
subtree_class={"Aircraft/c172p":"base","Aircraft/Generic":"base","Aircraft/Instruments":"base","Aircraft/Instruments-3d":"base","Aircraft/ufo":"base","Textures":"textures","Textures.high":"textures","AI/Aircraft":"ai","AI/Traffic":"ai","AI/Aircraft/performancedb.xml":"base","Scenery":"scenery","Models":"models"}
|
||||
for aircraft in include_aircraft:
|
||||
if "Aircraft/"+aircraft not in subtree_class:
|
||||
subtree_class["Aircraft/"+aircraft]="aircraft"
|
||||
include_files=[]
|
||||
if split_textures:
|
||||
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, 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
|
||||
if compressed_format==".jpg":
|
||||
print("Warning: selected compression format does not support transparency")
|
||||
compress_names=set()
|
||||
if dirs_to_compress:#need this preliminary pass to get names to change in .xml,etc
|
||||
no_compress_names=set()
|
||||
dirs={"":"base"}
|
||||
while dirs:
|
||||
cdir,cclass=dirs.popitem()
|
||||
cdirfiles=os.listdir(path_join(input_path,cdir))
|
||||
for file in cdirfiles:
|
||||
fclass=subtree_class.get(path_join(cdir,file),cclass)
|
||||
if os.path.isdir(path_join(input_path,cdir,file)):
|
||||
if (path_join(cdir,file) not in exclude_dirs) and (cdir not in exclude_unnamed_subdirs or path_join(cdir,file) in subtree_class):
|
||||
dirs[path_join(cdir,file)]=fclass
|
||||
else:#file
|
||||
compress_this=cdir.startswith(dirs_to_compress) and (os.path.splitext(file)[1] in texture_filetypes) and (os.path.splitext(file)[1]!=compressed_format) and (os.path.getsize(path_join(input_path,cdir,file))>compress_min_filesize) and not no_compress_pattern.search(file) and not cdir.startswith(no_compress_dirs) and (file not in no_compress_names) and ((use_ready_compressed is not None) or not os.path.exists(path_join(input_path,cdir,os.path.splitext(file)[0]+compressed_format)))
|
||||
if compress_this:
|
||||
compress_names.add(file)
|
||||
else:
|
||||
no_compress_names.add(file)
|
||||
compress_names.discard(file)#if there are two with the same name in different directories, compress both or neither, to simplify name replacement
|
||||
compress_names_find=re.compile(('(?<=["\'>/\\\\ \\n])('+'|'.join(re.escape(f) for f in compress_names)+')($|(?=["\'< \\n]))').encode('utf-8'))
|
||||
compress_names_find0=re.compile(('|'.join(re.escape(f) for f in compress_names)).encode('utf-8'))
|
||||
#print(compress_names,"\n\n",no_compress_names,"\n\n",'(?<=["\'>/\\\\ \\n])('+'|'.join(re.escape(f) for f in compress_names)+')($|(?=["\'< \\n]))',"\n\n",'|'.join(re.escape(f) for f in compress_names),"\n\n")
|
||||
print("Starting conversion...",len(compress_names),"files to change format, runtime so far=",int(time.time()-start_time),"sec")
|
||||
dirs={"":"base"}
|
||||
subprocess_pool=multiprocessing.Pool(processes=8)
|
||||
subprocess_list=[]
|
||||
temp_dir=tempfile.TemporaryDirectory()
|
||||
temp_path=temp_dir.name
|
||||
while dirs:
|
||||
cdir,cclass=dirs.popitem()
|
||||
cdirfiles=os.listdir(path_join(input_path,cdir))
|
||||
for file in cdirfiles:
|
||||
fclass=subtree_class.get(path_join(cdir,file),cclass)
|
||||
if os.path.isdir(path_join(input_path,cdir,file)):
|
||||
if (path_join(cdir,file) not in exclude_dirs) and (cdir not in exclude_unnamed_subdirs or path_join(cdir,file) in subtree_class):
|
||||
dirs[path_join(cdir,file)]=fclass
|
||||
else:#file
|
||||
if split_textures and fclass=="textures":
|
||||
if path_join(cdir,file) in base_texture_files:
|
||||
fclass="base-textures"
|
||||
else:
|
||||
fclass="extra-textures"
|
||||
if fclass in exclude_parts:
|
||||
continue
|
||||
if not os.path.exists(path_join(output_path.format(fclass),cdir)):
|
||||
os.makedirs(path_join(output_path.format(fclass),cdir))#errors out if the directory does exist, so calling it in the per-file subprocess would be a race condition
|
||||
if "{0}" in output_path and fclass=="base-textures" and not os.path.exists(path_join(output_path.format("extra-textures"),cdir)):#downsampled in base-textures, full resolution in extra-textures
|
||||
os.makedirs(path_join(output_path.format("extra-textures"),cdir))
|
||||
if not os.path.exists(path_join(temp_path,cdir)):
|
||||
os.makedirs(path_join(temp_path,cdir))
|
||||
downsample_this=(cdir.startswith(dirs_to_downsample)) and (os.path.splitext(file)[1] in texture_filetypes) and (os.path.getsize(path_join(input_path,cdir,file))>downsample_min_filesize)
|
||||
compress_this=(file in compress_names)
|
||||
if compress_this and use_ready_compressed==True and os.path.exists(path_join(input_path,cdir,os.path.splitext(file)[0]+compressed_format)):
|
||||
continue
|
||||
if (not compress_this) and use_ready_compressed==False and os.path.splitext(file)[1]==compressed_format and any((os.path.exists(path_join(input_path,cdir,os.path.splitext(file)[0]+f)) and os.path.splitext(file)[0]+f in compress_names) for f in texture_filetypes if f!=os.path.splitext(file)[1]):
|
||||
continue
|
||||
subprocess_list.append(subprocess_pool.apply_async(create_reduced_file,args=(input_path,output_path,temp_path,cdir,file,downsample_this,compress_this,compress_names_find, compressed_format,texture_filetypes,binary_types,fclass)))
|
||||
print(len(subprocess_list),"file tasks started...runtime so far=",int(time.time()-start_time),"sec\n(Not a linear progress indicator: they are different lengths.)")
|
||||
last_report=time.time()-100#print first report immediately
|
||||
for s0 in subprocess_list:
|
||||
if time.time()>last_report+60:
|
||||
print("Waiting for",len([s for s in subprocess_list if not s.ready()]),"file tasks...runtime so far=",int(time.time()-start_time),"sec")
|
||||
last_report=time.time()
|
||||
s0.get()
|
||||
subprocess_pool.close()
|
||||
subprocess_pool.join()
|
||||
if "{0}" in output_path:
|
||||
os.rename(path_join(output_path.format("base"),"preferences.xml"),path_join(output_path.format("base"),"preferences-regions.xml"))
|
||||
if "extra-textures" in exclude_parts or "{0}" in output_path:
|
||||
prefs_in=open(path_join(input_path,"preferences.xml"),'r')
|
||||
prefs_out=open(path_join(output_path.format("base"),"preferences-noregions.xml" if "{0}" in output_path else "preferences.xml"),'w')
|
||||
prefs_str=prefs_in.read(None)
|
||||
prefs_in.close()
|
||||
prefs_str=prefs_str.replace("Materials/regions/materials.xml","Materials/default/materials.xml")#turn off regional textures
|
||||
prefs_out.write(prefs_str)
|
||||
prefs_out.close()
|
||||
print("Total runtime=",int(time.time()-start_time),"sec")
|
||||
def check_text_encoding(path,filelist=None,binary_types=(".png",".dds",".rgb",".RGB",".jpg",".wav",".WAV",".btg.gz",".xcf.gz",".xcf",".XCF","Thumbs.db",".blend",".bmp",".gif", ".3ds",".3DS",".pdf",".ttf",".txf",".htsvoice",".odt",".ods",".xls",".mp3",".zip",".tar.gz"),exclude_dirs=[".git","Timezone"]):
|
||||
"""filelist is intended for quick testing: see fgdata_nonascii_filelist.py"""
|
||||
def err_context(err):
|
||||
start=max(err.object.rfind(b'\n',0,err.start)+1,err.start-30,0)
|
||||
end=min(err.object.find(b'\n',err.start),err.start+30,len(err.object))
|
||||
if end<0:#not found
|
||||
end=err.start+30
|
||||
return err.object[start:end]
|
||||
def dict_print(d):
|
||||
return "".join(i[0]+"\n\t"+str(i[1])+"\n\t"+(str(i[1],encoding="utf-8",errors="replace")+"\n\t"+str(i[1],encoding="latin-1") if type(i[1])==bytes else "")+"\n" for i in sorted(d.items()))
|
||||
if filelist is None:
|
||||
filelist=[f for f in rfilelist(path,exclude_dirs) if not f.endswith(tuple(binary_types))]
|
||||
utf8_files={}
|
||||
withnulls_files=[]
|
||||
othertext_files={}
|
||||
mislabeled_xml={}
|
||||
mislabeled_xml_nocomments={}
|
||||
xml_encoding_pattern=re.compile(r'<\?xml.*?encoding="(\S+?)".*?\?>')
|
||||
xml_noencoding_pattern=re.compile(r'<\?xml.*?\?>')
|
||||
utf8_files_nocomments={}
|
||||
othertext_files_nocomments={}
|
||||
for fname in filelist:
|
||||
if os.path.splitext(fname)[1]==".gz":
|
||||
fobj=gzip.open(path_join(path,fname),mode='rb')
|
||||
else:
|
||||
fobj=open(path_join(path,fname),mode='rb')
|
||||
fdata=fobj.read()
|
||||
if b"\0" in fdata:
|
||||
withnulls_files.append(fname)#two look like corrupted files: Aircraft/p51d/Resources/WIP/P-51D-25NA.ac (hangs gedit,large block of nulls in middle) Docs/Serial/nmeafaq.txt (block of nulls at end), rest are probably-binary types
|
||||
continue
|
||||
if os.path.splitext(fname)[1] in (".xml",".svg",".xhtml"):
|
||||
encoding_mark=xml_encoding_pattern.search(str(fdata.split(b'\n',maxsplit=1)[0],encoding="utf-8"))
|
||||
if encoding_mark:
|
||||
encoding_mark=encoding_mark.group(1)
|
||||
if encoding_mark not in ("utf-8","UTF-8","ISO-8859-1"):
|
||||
mislabeled_xml_nocomments[fname]="unrecognised encoding "+encoding_mark
|
||||
encoding_mark=None
|
||||
else:
|
||||
if xml_noencoding_pattern.search(str(fdata.split(b'\n',maxsplit=1)[0],encoding="utf-8")):
|
||||
encoding_mark="utf-8"#XML standard allows either UTF-8 or UTF-16 (with BOM) in unlabeled files, but we only use -8
|
||||
else:
|
||||
encoding_mark=None
|
||||
#mislabeled_xml_nocomments[fname]="no xml header"
|
||||
else:
|
||||
encoding_mark=None
|
||||
try:
|
||||
fdata.decode(encoding="ascii")
|
||||
continue
|
||||
except UnicodeError as err:
|
||||
errline=err_context(err)
|
||||
try:
|
||||
fdata.decode(encoding="utf-8")
|
||||
utf8_files[fname]=errline
|
||||
if encoding_mark not in ("utf-8","UTF-8",None):
|
||||
mislabeled_xml[fname]=bytes(encoding_mark,encoding="ascii")+errline
|
||||
except UnicodeError as err:
|
||||
errline=err_context(err)
|
||||
othertext_files[fname]=errline
|
||||
if encoding_mark not in ("ISO-8859-1",None):
|
||||
mislabeled_xml[fname]=bytes(encoding_mark,encoding="ascii")+errline
|
||||
if os.path.basename(fname) in ("Read-Me.txt","README.txt","Readme.txt","readme.txt","LIS-MOI_GNU-GPL"):
|
||||
continue
|
||||
fdata_nocomments=strip_comments(fdata,filename=fname)
|
||||
if fdata_nocomments.startswith(bytes([0xef,0xbb,0xbf])) and fname not in mislabeled_xml:#UTF-8 BOM
|
||||
fdata_nocomments=fdata_nocomments[3:]
|
||||
try:
|
||||
fdata_nocomments.decode(encoding="ascii")
|
||||
continue
|
||||
except UnicodeError as err:
|
||||
errline=err_context(err)
|
||||
try:
|
||||
fdata_nocomments.decode(encoding="utf-8")
|
||||
if encoding_mark is None:
|
||||
utf8_files_nocomments[fname]=errline
|
||||
if encoding_mark not in ("utf-8","UTF-8",None):
|
||||
mislabeled_xml_nocomments[fname]=bytes(encoding_mark,encoding="ascii")+errline
|
||||
except UnicodeError as err:
|
||||
errline=err_context(err)
|
||||
if encoding_mark is None:
|
||||
othertext_files_nocomments[fname]=errline
|
||||
if encoding_mark not in ("ISO-8859-1",None):
|
||||
mislabeled_xml_nocomments[fname]=bytes(encoding_mark,encoding="ascii")+errline
|
||||
print("non-ASCII valid UTF-8:",dict_print(utf8_files),"\n\nother:",dict_print(othertext_files),"\n\nmislabeled/unrecognised",dict_print(mislabeled_xml),"\n\nwith nulls (binary or UTF-16/32):",sorted(withnulls_files),"\n\nnon-ASCII valid UTF-8 (outside BOM/comments):",dict_print(utf8_files_nocomments),"\n\nother (outside comments):",dict_print(othertext_files_nocomments),"\n\nmislabeled/unrecognised (outside comments)",dict_print(mislabeled_xml_nocomments))
|
||||
|
||||
2
fgrun
2
fgrun
Submodule fgrun updated: ae0b0fef36...3fb3be1935
Submodule flightgear updated: 4873a28e97...f715a961f1
50
git_catalog_repository.py
Normal file
50
git_catalog_repository.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# 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
|
||||
34
git_discrete_repository.py
Normal file
34
git_discrete_repository.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# 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)
|
||||
|
||||
|
||||
|
||||
@@ -15,54 +15,47 @@ mkdir -p output
|
||||
rm -rf output/*
|
||||
rm -rf $WORKSPACE/dist/include/simgear $WORKSPACE/dist/libSim* $WORKSPACE/dist/libsg*.a
|
||||
|
||||
PATH=$PATH:$QTPATH
|
||||
echo "Build path is: $PATH"
|
||||
|
||||
###############################################################################
|
||||
echo "Starting on SimGear"
|
||||
pushd sgBuild
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -G Xcode ../simgear
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DENABLE_CURL:BOOL="ON" -DCMAKE_BUILD_TYPE=RelWithDebInfo ../simgear
|
||||
|
||||
# compile
|
||||
xcodebuild -configuration Release -target install build
|
||||
make
|
||||
|
||||
if [ $? -ne '0' ]; then
|
||||
echo "make simgear failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make install
|
||||
|
||||
|
||||
popd
|
||||
|
||||
################################################################################
|
||||
echo "Starting on FlightGear"
|
||||
pushd fgBuild
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -G Xcode ../flightgear
|
||||
cmake -DFG_NIGHTLY=1 -DCMAKE_INSTALL_PREFIX:PATH=$WORKSPACE/dist -DCMAKE_BUILD_TYPE=RelWithDebInfo ../flightgear
|
||||
|
||||
xcodebuild -configuration Release -target install build
|
||||
make
|
||||
|
||||
if [ $? -ne '0' ]; then
|
||||
echo "make flightgear failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make install
|
||||
|
||||
popd
|
||||
|
||||
chmod +x $WORKSPACE/dist/bin/osgversion
|
||||
|
||||
################################################################################
|
||||
echo "Building Macflightgear launcher"
|
||||
|
||||
OSX_TARGET="10.6"
|
||||
|
||||
pushd maclauncher/FlightGearOSX
|
||||
|
||||
# compile the stub executable
|
||||
gcc -o FlightGear -mmacosx-version-min=$OSX_TARGET -isysroot $SDK_PATH -arch i386 main.m \
|
||||
-framework Cocoa -framework RubyCocoa -framework Foundation -framework AppKit
|
||||
|
||||
popd
|
||||
|
||||
################################################################################
|
||||
echo "Syncing base packages files from sphere.telascience.org"
|
||||
rsync -avz --filter 'merge base-package.rules' \
|
||||
-e ssh jturner@sphere.telascience.org:/home/jturner/fgdata .
|
||||
|
||||
# run the unlock script now - we need to do this right before code-signing,
|
||||
# or the keychain may automatically re-lock after some period of time
|
||||
|
||||
@@ -7,6 +7,19 @@ include FileUtils
|
||||
$osgLibs = ['osgFX', 'osgParticle', 'osg', 'osgGA', 'osgText', 'osgUtil', 'osgSim', 'osgViewer', 'osgDB']
|
||||
$osgPlugins = ['ac', 'osg', 'freetype', 'imageio', 'rgb', 'txf', 'mdl', '3ds']
|
||||
|
||||
# from http://drawingablank.me/blog/ruby-boolean-typecasting.html
|
||||
class String
|
||||
def to_bool
|
||||
return true if self == true || self =~ (/^(true|t|yes|y|1)$/i)
|
||||
return false if self == false || self.blank? || self =~ (/^(false|f|no|n|0)$/i)
|
||||
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
||||
end
|
||||
end
|
||||
|
||||
class NilClass
|
||||
def to_bool; false; end
|
||||
end
|
||||
|
||||
def runOsgVersion(option)
|
||||
env = "export DYLD_LIBRARY_PATH=#{Dir.pwd}/dist/lib"
|
||||
bin = Dir.pwd + "/dist/bin/osgversion"
|
||||
@@ -19,65 +32,35 @@ $openThreadsSoVersion=runOsgVersion('openthreads-soversion-number')
|
||||
|
||||
$codeSignIdentity = ENV['FG_CODESIGN_IDENTITY']
|
||||
puts "Code signing identity is #{$codeSignIdentity}"
|
||||
|
||||
puts "osgVersion=#{osgVersion}, so-number=#{$osgSoVersion}"
|
||||
|
||||
$svnLibs = ['svn_client', 'svn_wc', 'svn_delta', 'svn_diff', 'svn_ra',
|
||||
'svn_ra_local', 'svn_repos', 'svn_fs', 'svn_fs_fs', 'svn_fs_util',
|
||||
'svn_ra_svn', 'svn_subr', 'svn_ra_neon']
|
||||
|
||||
def fix_install_names(object)
|
||||
#puts "fixing install names for #{object}"
|
||||
|
||||
$osgLibs.each do |l|
|
||||
oldName = "lib#{l}.#{$osgSoVersion}.dylib"
|
||||
newName = "@executable_path/../Frameworks/#{oldName}"
|
||||
`install_name_tool -change #{oldName} #{newName} #{object}`
|
||||
end
|
||||
|
||||
oldName = "libOpenThreads.#{$openThreadsSoVersion}.dylib"
|
||||
newName= "@executable_path/../Frameworks/#{oldName}"
|
||||
`install_name_tool -change #{oldName} #{newName} #{object}`
|
||||
end
|
||||
$isRelease = ENV['FG_IS_RELEASE'].to_bool
|
||||
puts "Is-release? : ##{$isRelease}"
|
||||
|
||||
$prefixDir=Dir.pwd + "/dist"
|
||||
dmgDir=Dir.pwd + "/image"
|
||||
srcDir=Dir.pwd + "/flightgear"
|
||||
|
||||
def fix_svn_install_names(object)
|
||||
$svnLibs.each do |l|
|
||||
fileName = "lib#{l}-1.0.dylib"
|
||||
newName = "@executable_path/../Frameworks/#{fileName}"
|
||||
`install_name_tool -change #{fileName} #{newName} #{object}`
|
||||
end
|
||||
end
|
||||
|
||||
def copy_svn_libs()
|
||||
puts "Copying Subversion client libraries"
|
||||
$svnLibs.each do |l|
|
||||
libFile = "lib#{l}-1.0.dylib"
|
||||
path = "#{$frameworksDir}/#{libFile}"
|
||||
`cp #{$prefixDir}/lib/#{libFile} #{$frameworksDir}`
|
||||
fix_svn_install_names(path)
|
||||
# `install_name_tool -id #{libFile} #{path}`
|
||||
end
|
||||
end
|
||||
|
||||
def code_sign(path)
|
||||
puts "Signing #{path}"
|
||||
`codesign -s "#{$codeSignIdentity}" #{path}`
|
||||
end
|
||||
|
||||
|
||||
puts "Erasing previous image dir"
|
||||
`rm -rf #{dmgDir}`
|
||||
|
||||
bundle=dmgDir + "/FlightGear.app"
|
||||
|
||||
# run macdeployt before we rename the bundle, otherwise it
|
||||
# can't find the bundle executable
|
||||
puts "Running macdeployqt on the bundle to copy Qt libraries"
|
||||
`macdeployqt #{$prefixDir}/fgfs.app`
|
||||
|
||||
puts "Moving & renaming app bundle"
|
||||
`mkdir -p #{dmgDir}`
|
||||
`mv #{$prefixDir}/fgfs.app #{bundle}`
|
||||
|
||||
bundle=dmgDir + "/FlightGear.app"
|
||||
contents=bundle + "/Contents"
|
||||
macosDir=contents + "/MacOS"
|
||||
$frameworksDir=contents +"/Frameworks"
|
||||
resourcesDir=contents+"/Resources"
|
||||
osgPluginsDir=contents+"/PlugIns/osgPlugins-#{osgVersion}"
|
||||
osgPluginsDir=contents+"/PlugIns/osgPlugins"
|
||||
|
||||
# for writing copyright year to Info.plist
|
||||
t = Time.new
|
||||
@@ -86,7 +69,13 @@ fgCurrentYear = t.year
|
||||
fgVersion = File.read("#{srcDir}/version").strip
|
||||
volName="\"FlightGear #{fgVersion}\""
|
||||
|
||||
dmgPath = Dir.pwd + "/output/fg_mac_#{fgVersion}.dmg"
|
||||
if $isRelease
|
||||
dmgPath = "" # no 'lite' build for release candidates
|
||||
dmgFullPath = Dir.pwd + "/output/FlightGear-#{fgVersion}.dmg"
|
||||
else
|
||||
dmgPath = Dir.pwd + "/output/FlightGear-#{fgVersion}-nightly.dmg"
|
||||
dmgFullPath = Dir.pwd + "/output/FlightGear-#{fgVersion}-nightly-full.dmg"
|
||||
end
|
||||
|
||||
puts "Creating directory structure"
|
||||
`mkdir -p #{macosDir}`
|
||||
@@ -94,24 +83,22 @@ puts "Creating directory structure"
|
||||
`mkdir -p #{resourcesDir}`
|
||||
`mkdir -p #{osgPluginsDir}`
|
||||
|
||||
puts "Copying binaries"
|
||||
bins = ['fgfs', 'fgjs', 'fgcom', 'fgviewer']
|
||||
|
||||
puts "Copying auxilliary binaries"
|
||||
bins = ['fgjs', 'fgcom']
|
||||
bins.each do |b|
|
||||
if !File.exist?("#{$prefixDir}/bin/#{b}")
|
||||
next
|
||||
end
|
||||
|
||||
|
||||
outPath = "#{macosDir}/#{b}"
|
||||
`cp #{$prefixDir}/bin/#{b} #{outPath}`
|
||||
fix_install_names(outPath)
|
||||
fix_svn_install_names(outPath)
|
||||
end
|
||||
|
||||
puts "copying libraries"
|
||||
$osgLibs.each do |l|
|
||||
libFile = "lib#{l}.#{$osgSoVersion}.dylib"
|
||||
`cp #{$prefixDir}/lib/#{libFile} #{$frameworksDir}`
|
||||
fix_install_names("#{$frameworksDir}/#{libFile}")
|
||||
end
|
||||
|
||||
# and not forgetting OpenThreads
|
||||
@@ -119,19 +106,8 @@ libFile = "libOpenThreads.#{$openThreadsSoVersion}.dylib"
|
||||
`cp #{$prefixDir}/lib/#{libFile} #{$frameworksDir}`
|
||||
|
||||
$osgPlugins.each do |p|
|
||||
pluginFile = "osgdb_#{p}.so"
|
||||
`cp #{$prefixDir}/lib/osgPlugins-#{osgVersion}/#{pluginFile} #{osgPluginsDir}`
|
||||
fix_install_names("#{osgPluginsDir}/#{pluginFile}")
|
||||
end
|
||||
|
||||
copy_svn_libs()
|
||||
|
||||
# Macflightgear launcher
|
||||
puts "Copying Macflightgear launcher files"
|
||||
|
||||
Dir.chdir "maclauncher/FlightGearOSX" do
|
||||
`cp FlightGear #{macosDir}`
|
||||
`rsync -a *.rb *.lproj *.sh *.tiff #{resourcesDir}`
|
||||
pluginFile = "osgdb_#{p}.dylib"
|
||||
`cp #{$prefixDir}/lib/osgPlugins/#{pluginFile} #{osgPluginsDir}`
|
||||
end
|
||||
|
||||
if File.exist?("#{$prefixDir}/bin/fgcom-data")
|
||||
@@ -150,21 +126,33 @@ File.open("#{contents}/Info.plist", 'w') { |f|
|
||||
`cp #{srcDir}/package/mac/FlightGear.icns #{resourcesDir}/FlightGear.icns`
|
||||
`cp #{srcDir}/COPYING #{dmgDir}`
|
||||
|
||||
puts "Copying base package files into the image"
|
||||
`rsync -a fgdata/ #{resourcesDir}/data`
|
||||
|
||||
# code sign all executables in MacOS dir. Do this last since reource
|
||||
# changes will invalidate the signature!
|
||||
Dir.foreach(macosDir) do |b|
|
||||
if b == '.' or b == '..' then
|
||||
next
|
||||
end
|
||||
code_sign("#{macosDir}/#{b}")
|
||||
end
|
||||
|
||||
puts "Creating DMG"
|
||||
# move documentation to a public place
|
||||
`cp fgdata/Docs/FGShortRef.pdf "#{dmgDir}/Quick Reference.pdf"`
|
||||
`cp fgdata/Docs/getstart.pdf "#{dmgDir}/Getting Started.pdf"`
|
||||
|
||||
createArgs = "-format UDBZ -imagekey bzip2-level=9 -quiet -volname #{volName}"
|
||||
|
||||
`rm #{dmgPath}`
|
||||
`hdiutil create -srcfolder #{dmgDir} #{createArgs} #{dmgPath}`
|
||||
|
||||
if !$isRelease
|
||||
# create the 'lite' DMG without the base files
|
||||
|
||||
# code sign the entire bundle once complete - v2 code-signing
|
||||
puts "Signing #{bundle}"
|
||||
`codesign --deep -s "#{$codeSignIdentity}" #{bundle}`
|
||||
puts "Creating DMG"
|
||||
|
||||
`rm #{dmgPath}`
|
||||
`hdiutil create -srcfolder #{dmgDir} #{createArgs} #{dmgPath}`
|
||||
end
|
||||
|
||||
puts "Creating full image with data"
|
||||
|
||||
puts "Copying base package files into the image"
|
||||
`rsync -a fgdata/ #{resourcesDir}/data`
|
||||
|
||||
# re-sign the entire bundle
|
||||
puts "Re-signing full #{bundle}"
|
||||
`codesign --force --deep -s "#{$codeSignIdentity}" #{bundle}`
|
||||
|
||||
`rm #{dmgFullPath}`
|
||||
`hdiutil create -srcfolder #{dmgDir} #{createArgs} #{dmgFullPath}`
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
IF NOT DEFINED WORKSPACE SET WORKSPACE=%~dp0
|
||||
|
||||
ECHO #define SIMGEAR_VERSION "2.9.0" > %WORKSPACE%\simgear\simgear\version.h
|
||||
rem set PATH=%PATH%;D:\Program Files (x86)\CMake 2.8\bin
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\vsvars32.bat"
|
||||
md build-sg
|
||||
md build-fg
|
||||
md build-fgrun
|
||||
cd build-sg
|
||||
cmake ..\simgear -G "Visual Studio 10" -DMSVC_3RDPARTY_ROOT=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100/SimGear -DBOOST_ROOT=%WORKSPACE%/Boost
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fg
|
||||
cmake ..\flightgear -G "Visual Studio 10" -DMSVC_3RDPARTY_ROOT=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100/FlightGear -DFLTK_FLUID_EXECUTABLE=%WORKSPACE%/3rdParty/bin/fluid.exe -DBOOST_ROOT=%WORKSPACE%/Boost
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fgrun
|
||||
cmake ..\fgrun -G "Visual Studio 10" -DMSVC_3RDPARTY_ROOT:PATH=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100/FGRun -DFLTK_FLUID_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/fluid.exe -DGETTEXT_MSGFMT_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/msgfmt.exe -DGETTEXT_MSGMERGE_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/msgmerge.exe -DBOOST_ROOT=%WORKSPACE%/Boost
|
||||
cmake --build . --config Release --target INSTALL
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
IF NOT DEFINED WORKSPACE SET WORKSPACE=%~dp0
|
||||
|
||||
ECHO #define SIMGEAR_VERSION "2.9.0" > %WORKSPACE%\simgear\simgear\version.h
|
||||
rem set PATH=%PATH%;D:\Program Files (x86)\CMake 2.8\bin
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64
|
||||
md build-sg64
|
||||
md build-fg64
|
||||
md build-fgrun64
|
||||
cd build-sg64
|
||||
cmake ..\SimGear -G "Visual Studio 10 Win64" -DMSVC_3RDPARTY_ROOT=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100-64/SimGear -DBOOST_ROOT=%WORKSPACE%/Boost
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fg64
|
||||
cmake ..\flightgear -G "Visual Studio 10 Win64" -DMSVC_3RDPARTY_ROOT=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100-64/FlightGear -DFLTK_FLUID_EXECUTABLE=%WORKSPACE%/3rdParty/bin/fluid.exe -DBOOST_ROOT=%WORKSPACE%/Boost -DWITH_FGPANEL=OFF -DENABLE_PROFILE=OFF
|
||||
cmake --build . --config Release --target INSTALL
|
||||
|
||||
cd ..\build-fgrun64
|
||||
cmake ..\fgrun -G "Visual Studio 10 Win64" -DMSVC_3RDPARTY_ROOT:PATH=%WORKSPACE% -DCMAKE_INSTALL_PREFIX:PATH=%WORKSPACE%/install/msvc100-64/FGRun -DFLTK_FLUID_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/fluid.exe -DGETTEXT_MSGFMT_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/msgfmt.exe -DGETTEXT_MSGMERGE_EXECUTABLE:FILEPATH=%WORKSPACE%/3rdParty/bin/msgmerge.exe -DBOOST_ROOT=%WORKSPACE%/Boost
|
||||
cmake --build . --config Release --target INSTALL
|
||||
@@ -1,30 +0,0 @@
|
||||
ECHO OFF
|
||||
|
||||
IF NOT DEFINED WORKSPACE SET WORKSPACE=%~dp0
|
||||
ECHO Packaging root is %WORKSPACE%
|
||||
|
||||
subst X: /D
|
||||
subst X: %WORKSPACE%.
|
||||
|
||||
REM construct information file to be read by Inno-setup
|
||||
|
||||
|
||||
set PATH=%WORKSPACE%\install\msvc100\OpenSceneGraph\bin;%PATH%
|
||||
REM indirect way to get command output into an environment variable
|
||||
osgversion --so-number > %TEMP%\osg-so-number.txt
|
||||
osgversion --version-number > %TEMP%\osg-version.txt
|
||||
|
||||
SET /P FLIGHTGEAR_VERSION=<flightgear\version
|
||||
SET /P OSG_VERSION=<%TEMP%\osg-version.txt
|
||||
SET /P OSG_SO_NUMBER=<%TEMP%\osg-so-number.txt
|
||||
|
||||
ECHO #define FGVersion "%FLIGHTGEAR_VERSION%" > InstallConfig.iss
|
||||
ECHO #define OSGVersion "%OSG_VERSION%" >> InstallConfig.iss
|
||||
ECHO #define OSGSoNumber "%OSG_SO_NUMBER%" >> InstallConfig.iss
|
||||
|
||||
REM run Inno-setup!
|
||||
|
||||
Compil32 /cc FlightGear.iss
|
||||
|
||||
|
||||
|
||||
20
installWinDeps.bat
Normal file
20
installWinDeps.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
REM ExternalProject can't cleanly extract a zip into an existing directory
|
||||
REM Instead we extract to a subdir, and then move the directories we want
|
||||
REM using this bat file.
|
||||
REM This script is used by the SuperBuild CMakeLists.txt
|
||||
|
||||
echo %CD%
|
||||
IF EXIST winDeps/3rdParty (
|
||||
md 3rdParty
|
||||
xcopy /Y /E winDeps/3rdParty 3rdParty
|
||||
echo "Done copying Windows deps"
|
||||
) ELSE (
|
||||
IF EXIST winDeps/3rdParty.x64 (
|
||||
md 3rdParty.x64
|
||||
xcopy /Y /E winDeps/3rdParty.x64 3rdParty.x64
|
||||
echo "Done copying Windows deps"
|
||||
) ELSE (
|
||||
echo "Error: Windows deps not found"
|
||||
exit -1
|
||||
)
|
||||
)
|
||||
Submodule maclauncher deleted from 7ffef2cb26
226
maintain_catalog.py
Executable file
226
maintain_catalog.py
Executable file
@@ -0,0 +1,226 @@
|
||||
#!/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
Normal file
239
package.py
Normal file
@@ -0,0 +1,239 @@
|
||||
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
|
||||
128
post_upload.py
Normal file
128
post_upload.py
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# this file runs on the download server (download.flightgear.org)
|
||||
# from the Jenkins upload-via-ssh jobs. It ensures that only complete
|
||||
# uploads are visible (and mirrored to SF).
|
||||
|
||||
import os, sys, re, fnmatch
|
||||
from subprocess import call
|
||||
|
||||
suffix = '.dmg'
|
||||
if sys.argv[1] == 'windows':
|
||||
suffix = '.exe'
|
||||
if sys.argv[1] == 'linux':
|
||||
suffix = '.tar.bz2'
|
||||
|
||||
isReleaseCandidate = False
|
||||
if len(sys.argv) > 2 and sys.argv[2] == 'release':
|
||||
isReleaseCandidate = True
|
||||
|
||||
allSuffix = '*' + suffix
|
||||
|
||||
print "Wildcard pattern is:" + allSuffix
|
||||
pattern = r'\w+-(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)([\w-]*)' + suffix
|
||||
sourceForgeUserHost = "jmturner@frs.sourceforge.net"
|
||||
sftpCommandFile = "sftp-commands"
|
||||
symbolDir = "/home/jenkins/symbols"
|
||||
|
||||
if isReleaseCandidate:
|
||||
publicRoot = "/var/www/html/builds/rc"
|
||||
incomingDir = "/home/jenkins/incoming"
|
||||
sourceForgePath = "/home/frs/project/f/fl/flightgear/release-candidate/"
|
||||
else:
|
||||
publicRoot = "/var/www/html/builds/nightly"
|
||||
incomingDir = "/home/jenkins/nightly-incoming"
|
||||
sourceForgePath = "/home/frs/project/f/fl/flightgear/unstable/"
|
||||
|
||||
os.chdir(publicRoot)
|
||||
|
||||
def findFileVersion(dir):
|
||||
for file in os.listdir(dir):
|
||||
if fnmatch.fnmatch(file, allSuffix):
|
||||
m = re.match(pattern, file)
|
||||
if (m is not None):
|
||||
return (m.group('major'), m.group('minor'), m.group('patch'))
|
||||
|
||||
return None
|
||||
|
||||
incomingVer = findFileVersion(incomingDir)
|
||||
if incomingVer is None:
|
||||
print "No incoming files found matching " + allSuffix
|
||||
exit()
|
||||
|
||||
existingVer = findFileVersion('.')
|
||||
|
||||
# if files in dest location mis-match the version, archive them
|
||||
# and re-create the symlinks
|
||||
|
||||
versionChange = (existingVer != incomingVer)
|
||||
|
||||
oldFiles = []
|
||||
incomingFiles = []
|
||||
newFiles = []
|
||||
|
||||
if versionChange:
|
||||
print "Version number changing"
|
||||
|
||||
for file in os.listdir('.'):
|
||||
if fnmatch.fnmatch(file, allSuffix):
|
||||
if not os.path.islink(file):
|
||||
oldFiles.append(file)
|
||||
os.remove(file)
|
||||
|
||||
for file in os.listdir(incomingDir):
|
||||
if fnmatch.fnmatch(file, allSuffix):
|
||||
incomingFiles.append(file)
|
||||
|
||||
# copy and symlink
|
||||
for file in incomingFiles:
|
||||
# move it to the public location
|
||||
srcFile = os.path.join(incomingDir, file)
|
||||
|
||||
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
|
||||
|
||||
os.rename(srcFile, outFile)
|
||||
newFiles.append(outFile)
|
||||
|
||||
if not isReleaseCandidate:
|
||||
# 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
|
||||
|
||||
print "Creating symlink from " + file + " to " + latestName
|
||||
if os.path.exists(latestName):
|
||||
print "\tremoving existing target"
|
||||
os.remove(latestName)
|
||||
os.symlink(file, latestName)
|
||||
|
||||
|
||||
# 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)
|
||||
|
||||
# upload to SourceForge
|
||||
for file in newFiles:
|
||||
print "Uploading " + file + " to SourceForge"
|
||||
call(["scp", file, sourceForgeUserHost + ":" + sourceForgePath + file])
|
||||
|
||||
if sys.argv[1] == 'windows':
|
||||
print "Archiving PDB files"
|
||||
for file in os.listdir(incomingDir):
|
||||
if fnmatch.fnmatch(file, "*.pdb"):
|
||||
srcFile = os.path.join(incomingDir, file)
|
||||
outFile = os.path.join(symbolDir, file)
|
||||
os.rename(srcFile, outFile)
|
||||
277
sgprops.py
Normal file
277
sgprops.py
Normal file
@@ -0,0 +1,277 @@
|
||||
# SAX for parsing
|
||||
from xml.sax import make_parser, handler, expatreader
|
||||
|
||||
# ElementTree for writing
|
||||
import xml.etree.cElementTree as ET
|
||||
|
||||
import re, os
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, name = '', index = 0, parent = None):
|
||||
self._parent = parent
|
||||
self._name = name
|
||||
self._value = None
|
||||
self._index = index
|
||||
self._children = []
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
@value.setter
|
||||
def value(self, v):
|
||||
self._value = v
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def index(self):
|
||||
return self._index
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self._parent
|
||||
|
||||
def getChild(self, n, i=None, create = False):
|
||||
|
||||
if i is None:
|
||||
i = 0
|
||||
# parse name as foo[999] if necessary
|
||||
m = re.match(R"(\w+)\[(\d+)\]", n)
|
||||
if m is not None:
|
||||
n = m.group(1)
|
||||
i = int(m.group(2))
|
||||
|
||||
for c in self._children:
|
||||
if (c.name == n) and (c.index == i):
|
||||
return c
|
||||
|
||||
if create:
|
||||
c = Node(n, i, self)
|
||||
self._children.append(c)
|
||||
return c
|
||||
else:
|
||||
raise IndexError("no such child:" + str(n) + " index=" + str(i))
|
||||
|
||||
def addChild(self, n):
|
||||
# adding an existing instance
|
||||
if isinstance(n, Node):
|
||||
n._parent = self
|
||||
n._index = self.firstUnusedIndex(n.name)
|
||||
self._children.append(n)
|
||||
return n
|
||||
|
||||
i = self.firstUnusedIndex(n)
|
||||
# create it via getChild
|
||||
return self.getChild(n, i, create=True)
|
||||
|
||||
def firstUnusedIndex(self, n):
|
||||
usedIndices = frozenset(c.index for c in self.getChildren(n))
|
||||
i = 0
|
||||
while i < 1000:
|
||||
if i not in usedIndices:
|
||||
return i
|
||||
i += 1
|
||||
raise RuntimeException("too many children with name:" + n)
|
||||
|
||||
def hasChild(self, nm):
|
||||
for c in self._children:
|
||||
if (c.name == nm):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def getChildren(self, n = None):
|
||||
if n is None:
|
||||
return self._children
|
||||
|
||||
return [c for c in self._children if c.name == n]
|
||||
|
||||
def getNode(self, path, cr = False):
|
||||
axes = path.split('/')
|
||||
nd = self
|
||||
for ax in axes:
|
||||
nd = nd.getChild(ax, create = cr)
|
||||
|
||||
return nd
|
||||
|
||||
def getValue(self, path, default = None):
|
||||
try:
|
||||
nd = self.getNode(path)
|
||||
return nd.value
|
||||
except:
|
||||
return default
|
||||
|
||||
def write(self, path):
|
||||
root = self._createXMLElement('PropertyList')
|
||||
t = ET.ElementTree(root)
|
||||
t.write(path, 'utf-8', xml_declaration = True)
|
||||
|
||||
def _createXMLElement(self, nm = None):
|
||||
if nm is None:
|
||||
nm = self.name
|
||||
|
||||
n = ET.Element(nm)
|
||||
|
||||
# value and type specification
|
||||
try:
|
||||
if self._value is not None:
|
||||
if isinstance(self._value, basestring):
|
||||
# don't call str() on strings, breaks the
|
||||
# encoding
|
||||
n.text = self._value
|
||||
else:
|
||||
# use str() to turn non-string types into text
|
||||
n.text = str(self._value)
|
||||
if isinstance(self._value, int):
|
||||
n.set('type', 'int')
|
||||
elif isinstance(self._value, float):
|
||||
n.set('type', 'double')
|
||||
elif isinstance(self._value, bool):
|
||||
n.set('type', "bool")
|
||||
except UnicodeEncodeError:
|
||||
print "Encoding error with", self._value, type(self._value)
|
||||
|
||||
# index in parent
|
||||
if (self.index != 0):
|
||||
n.set('n', str(self.index))
|
||||
|
||||
# children
|
||||
for c in self._children:
|
||||
n.append(c._createXMLElement())
|
||||
|
||||
return n;
|
||||
|
||||
|
||||
class PropsHandler(handler.ContentHandler):
|
||||
def __init__(self, root = None, path = None, includePaths = []):
|
||||
self._root = root
|
||||
self._path = path
|
||||
self._basePath = os.path.dirname(path)
|
||||
self._includes = includePaths
|
||||
self._locator = None
|
||||
|
||||
if root is None:
|
||||
# make a nameless root node
|
||||
self._root = Node("", 0)
|
||||
self._current = self._root
|
||||
|
||||
def setDocumentLocator(self, loc):
|
||||
self._locator = loc
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
self._content = None
|
||||
if (name == 'PropertyList'):
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
self._current = self._current.getChild(name, index, create=True)
|
||||
else:
|
||||
self._current = self._current.addChild(name)
|
||||
|
||||
|
||||
if 'include' in attrs.keys():
|
||||
self.handleInclude(attrs['include'])
|
||||
|
||||
self._currentTy = None;
|
||||
if 'type' in attrs.keys():
|
||||
self._currentTy = attrs['type']
|
||||
|
||||
def handleInclude(self, includePath):
|
||||
if includePath.startswith('/'):
|
||||
includePath = includePath[1:]
|
||||
|
||||
p = os.path.join(self._basePath, includePath)
|
||||
if not os.path.exists(p):
|
||||
found = False
|
||||
for i in self._includes:
|
||||
p = os.path.join(i, includePath)
|
||||
if os.path.exists(p):
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise RuntimeError("include file not found", includePath, "at line", self._locator.getLineNumber())
|
||||
|
||||
readProps(p, self._current, self._includes)
|
||||
|
||||
def endElement(self, name):
|
||||
if (name == 'PropertyList'):
|
||||
return
|
||||
|
||||
try:
|
||||
# convert and store value
|
||||
self._current.value = self._content
|
||||
if self._currentTy == "int":
|
||||
self._current.value = int(self._content) if self._content is not None else 0
|
||||
if self._currentTy == "bool":
|
||||
self._current.value = self.parsePropsBool(self._content)
|
||||
if self._currentTy == "double":
|
||||
if self._content is None:
|
||||
self._current.value = 0.0
|
||||
else:
|
||||
if self._content.endswith('f'):
|
||||
self._content = self._content[:-1]
|
||||
self._current.value = float(self._content)
|
||||
except:
|
||||
print "Parse error for value:", self._content, "at line:", self._locator.getLineNumber(), "of:", self._path
|
||||
|
||||
self._current = self._current.parent
|
||||
self._content = None
|
||||
self._currentTy = None
|
||||
|
||||
|
||||
def parsePropsBool(self, content):
|
||||
if content == "True" or content == "true":
|
||||
return True
|
||||
|
||||
if content == "False" or content == "false":
|
||||
return False
|
||||
|
||||
try:
|
||||
icontent = int(content)
|
||||
if icontent is not None:
|
||||
if icontent == 0:
|
||||
return False
|
||||
else:
|
||||
return True;
|
||||
except:
|
||||
return False
|
||||
|
||||
def characters(self, content):
|
||||
if self._content is None:
|
||||
self._content = ''
|
||||
self._content += content
|
||||
|
||||
def endDocument(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def root(self):
|
||||
return self._root
|
||||
|
||||
def readProps(path, root = None, includePaths = []):
|
||||
parser = make_parser()
|
||||
locator = expatreader.ExpatLocator( parser )
|
||||
h = PropsHandler(root, path, includePaths)
|
||||
h.setDocumentLocator(locator)
|
||||
parser.setContentHandler(h)
|
||||
parser.parse(path)
|
||||
return h.root
|
||||
|
||||
def copy(src, dest):
|
||||
dest.value = src.value
|
||||
|
||||
# recurse over children
|
||||
for c in src.getChildren() :
|
||||
dc = dest.getChild(c.name, i = c.index, create = True)
|
||||
copy(c, dc)
|
||||
2
simgear
2
simgear
Submodule simgear updated: 724fba4af9...c92a953511
41
svn_catalog_repository.py
Normal file
41
svn_catalog_repository.py
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
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])
|
||||
52
template_catalog.xml
Normal file
52
template_catalog.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?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>
|
||||
|
||||
|
||||
19
webhooks.xml
Normal file
19
webhooks.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
The <regex> field is evaluated by preg_match
|
||||
http://php.net/manual/en/function.preg-match.php
|
||||
-->
|
||||
<PropertyList>
|
||||
<webhook>
|
||||
<regex>/^Merge branch/</regex>
|
||||
<description>Detect merge branch when rebase has been ommited</description>
|
||||
</webhook>
|
||||
<webhook>
|
||||
<regex>/^test$/</regex>
|
||||
<description>Detect for dummy message</description>
|
||||
</webhook>
|
||||
<webhook>
|
||||
<regex>/blabla/</regex>
|
||||
<description>Detect for bad commit description</description>
|
||||
</webhook>
|
||||
</PropertyList>
|
||||
1
windows-3rd-party
Submodule
1
windows-3rd-party
Submodule
Submodule windows-3rd-party added at 5b231bc794
Reference in New Issue
Block a user