1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3
4#-------------------------------------------------------------------------------
5
6# This file is part of Code_Saturne, a general-purpose CFD tool.
7#
8# Copyright (C) 1998-2021 EDF S.A.
9#
10# This program is free software; you can redistribute it and/or modify it under
11# the terms of the GNU General Public License as published by the Free Software
12# Foundation; either version 2 of the License, or (at your option) any later
13# version.
14#
15# This program is distributed in the hope that it will be useful, but WITHOUT
16# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18# details.
19#
20# You should have received a copy of the GNU General Public License along with
21# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22# Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
24#-------------------------------------------------------------------------------
25
26"""
27This module describes the script used to update a Code_Saturne case
28links and paths, as well as user functions examples.
29
30This module defines the following functions:
31- process_cmd_line
32- set_executable
33- unset_executable
34- update_case
35- main
36"""
37
38#-------------------------------------------------------------------------------
39# Library modules import
40#-------------------------------------------------------------------------------
41
42import os, sys, shutil, stat
43import types, string, re, fnmatch
44from optparse import OptionParser
45
46from code_saturne import cs_exec_environment
47from code_saturne import cs_runcase
48from code_saturne import cs_run_conf
49from code_saturne.cs_case import get_case_dir
50from code_saturne.cs_create import set_executable, unset_executable
51from code_saturne.cs_create import create_local_launcher
52
53#-------------------------------------------------------------------------------
54# Process the passed command line arguments
55#-------------------------------------------------------------------------------
56
57def process_cmd_line(argv, pkg):
58    """
59    Process the passed command line arguments.
60    """
61
62    if sys.argv[0][-3:] == '.py':
63        usage = "usage: %prog [options]"
64    else:
65        usage = "usage: %prog create [options]"
66
67    parser = OptionParser(usage=usage)
68
69    parser.add_option("-c", "--case", dest="case_names", type="string",
70                      metavar="<case>", action="append",
71                      help="case to update")
72
73    parser.add_option("-q", "--quiet",
74                      action="store_const", const=0, dest="verbose",
75                      help="do not output any information")
76
77    parser.add_option("-v", "--verbose",
78                      action="store_const", const=2, dest="verbose",
79                      help="dump study creation parameters")
80
81    parser.set_defaults(case_names=[])
82    parser.set_defaults(verbose=1)
83
84    (options, args) = parser.parse_args(argv)
85
86    return (options, args)
87
88#-------------------------------------------------------------------------------
89# Copy a directory without raising an error if the destination allready exists
90#
91# If ref is set to true, ignore the directory if the destination does not
92# exist, so that if the case was created with a "--noref" option, we  can
93# avoid adding references or examples in an update.
94# In this case, previous files are also removed, as they may be obsolete.
95#-------------------------------------------------------------------------------
96
97def copy_directory(src, dest, ref=False):
98
99    if not os.path.isdir(dest):
100        if ref == False:
101            shutil.copytree(src, dest)
102
103    else:
104        if ref:
105            for itm in os.listdir(dest):
106                os.remove(os.path.join(dest, itm))
107
108        for itm in os.listdir(src):
109            shutil.copy2(os.path.join(src, itm), os.path.join(dest, itm))
110
111#-------------------------------------------------------------------------------
112# Update the case paths and examples/reference files
113#-------------------------------------------------------------------------------
114
115def update_case(options, pkg):
116
117    topdir = os.getcwd()
118    study_name = os.path.basename(os.getcwd())
119
120    i_c = cs_run_conf.get_install_config_info(pkg)
121    resource_name = cs_run_conf.get_resource_name(i_c)
122
123    for case in options.case_names:
124        os.chdir(topdir)
125
126        if case == ".":
127            case, staging_dir = get_case_dir()
128            if not case:
129                sys.stderr.write("  o Skipping '%s', which  does not seem "
130                                 "to be a case directory\n" % topdir)
131                continue
132            casename = os.path.basename(case)
133        else:
134            casename = case
135
136        if options.verbose > 0:
137            sys.stdout.write("  o Updating case '%s' paths...\n" % casename)
138
139        datadir = os.path.join(pkg.get_dir("pkgdatadir"))
140
141        os.chdir(case)
142
143        # Write a local wrapper to main command
144        data = 'DATA'
145        if not os.path.isdir(data):
146            os.mkdir(data)
147
148        dataref_distpath = os.path.join(datadir, 'user')
149        user = os.path.join(data, 'REFERENCE')
150
151        # Only update user_scripts reference, not data
152        # (we should try to deprecate the copying of reference data
153        # or use the GUI to align it with the active options)
154        if os.path.exists(user):
155            abs_f = os.path.join(datadir, 'data', 'user', 'cs_user_scripts.py')
156            shutil.copy(abs_f, user)
157            unset_executable(user)
158
159        for s in ("SaturneGUI", "NeptuneGUI"):
160            old_gui_script = os.path.join(data, s)
161            if os.path.isfile(old_gui_script):
162                os.remove(old_gui_script)
163
164        # Rebuild launch script
165        create_local_launcher(pkg, data)
166
167        # User source files directory
168        src = 'SRC'
169        if not os.path.isdir(src):
170            os.mkdir(src)
171
172        user_ref_distpath = os.path.join(datadir, 'user_sources')
173        for srcdir in ('REFERENCE', 'EXAMPLES', 'EXAMPLES_neptune_cfd'):
174            if os.path.isdir(os.path.join(user_ref_distpath, srcdir)):
175                copy_directory(os.path.join(user_ref_distpath, srcdir),
176                               os.path.join(src, srcdir),
177                               True)
178
179            unset_executable(os.path.join(src, srcdir))
180
181        # Results directory (only one for all instances)
182
183        resu = 'RESU'
184        if not os.path.isdir(resu):
185            os.mkdir(resu)
186
187        # Script directory (only one for all instances)
188
189        run_conf_file = os.path.join(topdir, case, 'DATA', 'run.cfg')
190        batch_file = os.path.join(topdir, case, 'SCRIPTS', 'runcase')
191        if sys.platform.startswith('win'):
192            batch_file = batch_file + '.bat'
193
194        run_conf = cs_run_conf.run_conf(run_conf_file,
195                                        package=pkg,
196                                        rebuild=True)
197
198        if os.path.isfile(batch_file):
199            runcase = cs_runcase.runcase(batch_file,
200                                         package=pkg)
201            sections = runcase.run_conf_sections(resource_name=resource_name,
202                                                 batch_template=i_c['batch'])
203            for sn in sections:
204                if not sn in run_conf.sections:
205                    run_conf.sections[sn] = {}
206                for kw in sections[sn]:
207                    run_conf.sections[sn][kw] = sections[sn][kw]
208            os.remove(batch_file)
209            scripts_dir = os.path.join(topdir, case, 'SCRIPTS')
210            try:
211                os.rmdir(scripts_dir)
212            except Exception:
213                pass
214
215        run_conf.save()
216
217#-------------------------------------------------------------------------------
218# Main function
219#-------------------------------------------------------------------------------
220
221def main(argv, pkg):
222    """
223    Main function.
224    """
225
226    welcome = """\
227%(name)s %(vers)s case update
228"""
229    opts, args = process_cmd_line(argv, pkg)
230
231    if opts.case_names == []:
232        if len(args) > 0:
233            opts.case_names = args
234        else:
235            # Value is set to "." instead of "" to avoid chdir errors due
236            # to non existant paths
237            opts.case_names = ["."]
238
239    if opts.verbose > 0:
240        sys.stdout.write(welcome % {'name':pkg.name, 'vers':pkg.version})
241
242    update_case(opts, pkg)
243
244if __name__=="__main__":
245    main(sys.argv[1:], None)
246