1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "config.h"
6#include "environment.h"
7#include "processutil.h"
8
9#include <QRegularExpression>
10#include <QDir>
11#include <QDebug>
12#include <QDirIterator>
13
14#include <iostream>
15namespace environment {
16
17const QString RK_Major{"Major"};
18const QString RK_Minor{"Minor"};
19const QString RK_Revision{"Revision"};
20const QString RK_Build{"Build"};
21
22namespace language {
23
24Version completion(Category category, Kit kit, const Version &version)
25{
26 qInfo() << __FUNCTION__ << version.major.value();
27 Version ret = version;
28 if (category == User) {
29 if (kit == Python) {
30 QString program = "python";
31 if (version.major) {
32 program += QString::number(version.major.value());
33 }
34 ProcessUtil::execute(program, {"-V"}, [&](const QByteArray &data){
35 QRegularExpression regExp {"Python\\s(?<" + RK_Major +">[0-9])"
36 + "\\.(?<"+ RK_Minor +">[0-9])"
37 + "\\.(?<"+ RK_Revision +">[0-9])"
38 + "(\\.(?<"+ RK_Build + ">[0-9]))?"};
39 auto matchs = regExp.match(data);
40 if (matchs.hasMatch()) {
41 auto major = matchs.captured(RK_Major);
42 auto minor = matchs.captured(RK_Minor);
43 auto revsion = matchs.captured(RK_Revision);
44 auto build = matchs.captured(RK_Build);
45 if (!major.isNull()) {
46 ret.major = major.toInt();
47 }
48 if (!minor.isNull()) {
49 ret.minor = minor.toInt();
50 }
51 if (!revsion.isNull()) {
52 ret.revision = revsion.toInt();
53 }
54 if (!build.isNull()) {
55 ret.revision = build.toInt();
56 }
57 }
58 });
59 }
60 }
61 return ret;
62}
63
64Program search(Category category, Kit kit, const Version &version)
65{
66 qInfo() << __FUNCTION__;
67 Program ret;
68 if (category == User) {
69 if (kit == Python) {
70 Version executeVersion = completion(category, kit, version);
71 if (executeVersion.major.value() == 3) {
72 QString program = "python";
73 if (executeVersion.major) {
74 program + QString::number(executeVersion.major.value());
75 }
76 ret.pkgsPath = QDir::homePath() + QDir::separator()
77 + ".local" + QDir::separator()
78 + "lib" + QDir::separator()
79 + QString("python") + QString::number(executeVersion.major.value())
80 + "."
81 + QString::number(executeVersion.minor.value())
82 + QDir::separator()
83 + "site-packages";
84 }
85 }
86 }
87 return ret;
88}
89
90QProcessEnvironment get(Category category, Kit kit, const Version &version)
91{
92 QProcess process;
93 auto procEnv = process.processEnvironment();
94 if (category == Category::User) {
95 if (kit == Kit::Python) {
96 Program program = search(category, kit, version);
97 if (program.binsPath) {
98 QString runtimeBinPath = program.binsPath.value();
99 QString PATH_EnvValue = procEnv.value("PATH");
100 procEnv.remove("PATH");
101 procEnv.insert("PATH", runtimeBinPath + ":" + PATH_EnvValue);
102 }
103 if (program.pkgsPath) {
104 QString userPythonPkgPath = program.pkgsPath.value();
105 procEnv.remove("PYTHONPATH");
106 procEnv.insert("PYTHONPATH", userPythonPkgPath);
107 }
108 }
109 }
110 return procEnv;
111}
112
113Version::Version()
114{
115
116}
117
118Version::Version(int major)
119 : major(major)
120{
121
122}
123
124Version::Version(const Version &version)
125 : major(version.major)
126 , minor(version.minor)
127 , revision(version.revision)
128 , build(version.build)
129{
130
131}
132
133Version &Version::operator =(const Version &version)
134{
135 this->major = version.major;
136 this->minor = version.minor;
137 this->revision = version.revision;
138 this->build = version.build;
139 return *this;
140}
141
142} // language
143
144/*!
145 * @brief package::native::path
146 * get local install offline packge path
147 * @param category use package name to search
148 * @return if Category is empty return install top path, else return package name path
149 */
150QString package::native::path(const Category::type_value &category)
151{
152 QString envPath = QString(LIBRARY_INSTALL_PREFIX)
153 + QDir::separator() + "tools"
154 + QDir::separator() + "env";
155 if (category.isEmpty()) {
156 return envPath;
157 } else {
158 QDirIterator sameItera(envPath, QDir::Files|QDir::NoDotAndDotDot);
159 while (sameItera.hasNext()) {
160 sameItera.next();
161 QFileInfo info = sameItera.fileInfo();
162 if (category == info.fileName()) {
163 return info.filePath();
164 }
165 }
166 QDirIterator containsItera(envPath, QDir::Files|QDir::NoDotAndDotDot);
167 while (containsItera.hasNext()) {
168 containsItera.next();
169 QFileInfo info = containsItera.fileInfo();
170 if (info.fileName().contains(category)) {
171 return info.filePath();
172 }
173 }
174 }
175 return envPath;
176}
177
178/*!
179 * \brief environment::package::native::installed
180 * Determine whether the current offline package is installed
181 * \return if install return true, else return false
182 */
183bool environment::package::native::installed()
184{
185 QDir dir(path());
186 if (dir.exists())
187 return true;
188 return false;
189}
190
191} // environment
192