lbkit 0.6.2__tar.gz → 0.6.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {lbkit-0.6.2/lbkit.egg-info → lbkit-0.6.4}/PKG-INFO +1 -1
  2. lbkit-0.6.4/lbkit/__init__.py +2 -0
  3. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/codegen.py +4 -2
  4. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/idf_interface.py +115 -23
  5. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/client.c.mako +3 -0
  6. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/public.c.mako +3 -0
  7. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/server.c.mako +3 -0
  8. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/build.py +12 -4
  9. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/template/conanbase.mako +9 -10
  10. {lbkit-0.6.2 → lbkit-0.6.4/lbkit.egg-info}/PKG-INFO +1 -1
  11. lbkit-0.6.2/lbkit/__init__.py +0 -2
  12. {lbkit-0.6.2 → lbkit-0.6.4}/AUTHORS +0 -0
  13. {lbkit-0.6.2 → lbkit-0.6.4}/LICENSE +0 -0
  14. {lbkit-0.6.2 → lbkit-0.6.4}/MANIFEST.in +0 -0
  15. {lbkit-0.6.2 → lbkit-0.6.4}/README.md +0 -0
  16. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/build_conan_parallel.py +0 -0
  17. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/ci_robot/__init__.py +0 -0
  18. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/ci_robot/gitee.py +0 -0
  19. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/cli.py +0 -0
  20. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/__init__.py +0 -0
  21. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/ctype_defination.py +0 -0
  22. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/renderer.py +0 -0
  23. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/client.h.mako +0 -0
  24. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/interface.c.mako +0 -0
  25. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
  26. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/public.h.mako +0 -0
  27. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/codegen/template/server.h.mako +0 -0
  28. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/__init__.py +0 -0
  29. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/arg_parser.py +0 -0
  30. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/template/deploy.mako +0 -0
  31. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/component/test.py +0 -0
  32. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/errors.py +0 -0
  33. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/helper.py +0 -0
  34. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/__init__.py +0 -0
  35. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/build_image.py +0 -0
  36. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/build_manifest.py +0 -0
  37. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/build_prepare.py +0 -0
  38. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/build_rootfs.py +0 -0
  39. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/config.py +0 -0
  40. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/task.py +0 -0
  41. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/integration/template/conanfile.py.mako +0 -0
  42. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/lbkit.py +0 -0
  43. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/log.py +0 -0
  44. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/misc.py +0 -0
  45. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/tools.py +0 -0
  46. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/utils/__init__.py +0 -0
  47. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/utils/images/__init__.py +0 -0
  48. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit/utils/images/emmc.py +0 -0
  49. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit.egg-info/SOURCES.txt +0 -0
  50. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit.egg-info/dependency_links.txt +0 -0
  51. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit.egg-info/entry_points.txt +0 -0
  52. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit.egg-info/requires.txt +0 -0
  53. {lbkit-0.6.2 → lbkit-0.6.4}/lbkit.egg-info/top_level.txt +0 -0
  54. {lbkit-0.6.2 → lbkit-0.6.4}/setup.cfg +0 -0
  55. {lbkit-0.6.2 → lbkit-0.6.4}/setup.py +0 -0
  56. {lbkit-0.6.2 → lbkit-0.6.4}/test/__init__.py +0 -0
  57. {lbkit-0.6.2 → lbkit-0.6.4}/test/test_codegen.py +0 -0
  58. {lbkit-0.6.2 → lbkit-0.6.4}/test/test_helper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lbkit
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Tools provided by litebmc.com
5
5
  Home-page: https://www.litebmc.com
6
6
  Author: xuhj@litebmc.com
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = '0.6.4'
@@ -30,8 +30,7 @@ class CodeGen(object):
30
30
  os.makedirs(os.path.join(directory, "public"), exist_ok=True)
31
31
  os.makedirs(os.path.join(directory, "server"), exist_ok=True)
32
32
  os.makedirs(os.path.join(directory, "client"), exist_ok=True)
33
- lookup = TemplateLookup(directories=os.path.join(lb_cwd, "template"))
34
- interface = IdfInterface(lookup, idf_file)
33
+ interface = self.get_interface(idf_file)
35
34
  out_file = os.path.join(directory, "public", interface.name + ".xml")
36
35
  interface.render_dbus_xml("interface.introspect.xml.mako", out_file, self.codegen_version)
37
36
  for code_type in ["server", "client", "public"]:
@@ -54,6 +53,9 @@ class CodeGen(object):
54
53
  with open(odf_file, "w", encoding="utf-8") as fp:
55
54
  json.dump(odf_data, fp, sort_keys=False, indent=4)
56
55
 
56
+ def get_interface(self, idf_file):
57
+ lookup = TemplateLookup(directories=os.path.join(lb_cwd, "template"))
58
+ return IdfInterface(lookup, idf_file)
57
59
 
58
60
  def run(self):
59
61
  """
@@ -1,8 +1,8 @@
1
- import yaml
2
1
  import os
3
2
  import re
4
3
  import copy
5
4
  import hashlib
5
+ from functools import cached_property
6
6
  from lbkit.log import Logger
7
7
  from lbkit.codegen.renderer import Renderer
8
8
  from lbkit.codegen.ctype_defination import CTYPE_OBJS, RefObjArrayValidator, RefObjValidator
@@ -113,20 +113,34 @@ def ctype_to_variant_signature(intf: IdfInterfaceBase, ctype: str):
113
113
  match = re.match(f"^(struct|enum|dict)\[(.*)\]$", ctype)
114
114
 
115
115
  match_intf, match_ctype = get_intfname_and_ctype(match.group(2))
116
+ if match_intf != "self":
117
+ intf = intf.dependency_idf_interface[match_intf]
116
118
  if match.group(1) == "struct":
117
- if match_intf == "self":
118
- stru = intf.structures.get(match_ctype)
119
- if stru is None:
120
- raise IDFException(f"Unknown structure {match_ctype} get")
121
- return sig_prefix + stru.signature
119
+ stru = intf.structures.get(match_ctype)
120
+ if stru is None:
121
+ raise IDFException(f"Unknown structure {match_ctype} get")
122
+ return sig_prefix + stru.signature
122
123
  elif match.group(1) == "enum":
123
124
  return sig_prefix + "s"
124
125
  else:
125
- if match_intf == "self":
126
- dictionary = intf.dictionaries.get(match_ctype)
127
- if dictionary is None:
128
- raise IDFException(f"Unknown structure {match_ctype} get")
129
- return sig_prefix + dictionary.signature
126
+ dictionary = intf.dictionaries.get(match_ctype)
127
+ if dictionary is None:
128
+ raise IDFException(f"Unknown structure {match_ctype} get")
129
+ return sig_prefix + dictionary.signature
130
+
131
+ def ctype_to_dependency_interface(ctype: str):
132
+ match = re.match(f"^array\[(.*)\]$", ctype)
133
+ if match is not None:
134
+ ctype = match.group(1)
135
+ match = re.match(f"^({CTYPE_REGEX})$", ctype)
136
+ if match is not None:
137
+ return []
138
+ match = re.match(f"^(struct|enum|dict)\[(.*)\]$", ctype)
139
+
140
+ match_intf, _ = get_intfname_and_ctype(match.group(2))
141
+ if match_intf == "self":
142
+ return []
143
+ return [match_intf]
130
144
 
131
145
 
132
146
  class IdfCtypeRender():
@@ -139,7 +153,7 @@ class IdfCtypeRender():
139
153
 
140
154
  def __init__(self):
141
155
  # 非基础类型
142
- match = re.match(f"^(set\[enum\[(.*)\]\])$", self.ctype)
156
+ match = re.match(f"^set\[enum\[(.*)\]\]$", self.ctype)
143
157
  # 如果set类型由转换成数组,当前不具备对set类型独立处理能力
144
158
  if match:
145
159
  self.ctype = f"array[enum[{match.group(1)}]]"
@@ -217,19 +231,23 @@ class IdfCtypeRender():
217
231
  is_array = True
218
232
  ctype = match.group(1)
219
233
  match = re.match(f"^(struct|enum|dict)\[(.*)\]$", ctype)
220
- _, stru_name = get_intfname_and_ctype(match.group(2))
234
+ intf_name, stru_name = get_intfname_and_ctype(match.group(2))
235
+ if intf_name == "self":
236
+ intf = self.intf
237
+ else:
238
+ intf = self.intf.dependency_idf_interface[intf_name]
221
239
  if match.group(1) == "struct":
222
- stru = self.intf.structures.get(stru_name)
240
+ stru = intf.structures.get(stru_name)
223
241
  if stru is None:
224
242
  raise IDFException(f"Structurer {stru_name} is not found, generate odf for {self.name} failed")
225
243
  schema = stru.odf_schema()
226
244
  elif match.group(1) == "enum":
227
- enum = self.intf.enumerations.get(stru_name)
245
+ enum = intf.enumerations.get(stru_name)
228
246
  if enum is None:
229
247
  raise IDFException(f"Enumerate {stru_name} is not found, generate odf for {self.name} failed")
230
248
  schema = enum.odf_schema()
231
249
  else:
232
- dict_cls = self.intf.dictionaries.get(stru_name)
250
+ dict_cls = intf.dictionaries.get(stru_name)
233
251
  if dict_cls is None:
234
252
  raise IDFException(f"Dictionary {stru_name} is not found, generate odf for {self.name} failed")
235
253
  schema = dict_cls.odf_schema()
@@ -730,6 +748,10 @@ class IdfProperty(IdfCtypeRender):
730
748
  def signature(self):
731
749
  return ctype_to_variant_signature(self.intf, self.ctype)
732
750
 
751
+ @cached_property
752
+ def dependency_interface(self):
753
+ return ctype_to_dependency_interface(self.ctype)
754
+
733
755
 
734
756
  class IdfParameter(IdfCtypeRender):
735
757
  def __init__(self, intf: IdfInterfaceBase, para_data):
@@ -744,6 +766,11 @@ class IdfParameter(IdfCtypeRender):
744
766
  def signature(self):
745
767
  return ctype_to_variant_signature(self.intf, self.ctype)
746
768
 
769
+ @cached_property
770
+ def dependency_interface(self):
771
+ return ctype_to_dependency_interface(self.ctype)
772
+
773
+
747
774
  class IdfParameters():
748
775
  def __init__(self, intf: IdfInterfaceBase, para_data):
749
776
  self.intf = intf
@@ -763,6 +790,14 @@ class IdfParameters():
763
790
  sig += para.signature
764
791
  return sig
765
792
 
793
+ @cached_property
794
+ def dependency_interface(self):
795
+ deps = []
796
+ for para in self.parameters:
797
+ deps.extend(para.dependency_interface)
798
+ return list(set(deps))
799
+
800
+
766
801
  class IdfBase():
767
802
  def __init__(self, intf: IdfInterfaceBase, data):
768
803
  self.intf = intf
@@ -795,6 +830,13 @@ class IdfMethod(IdfBase):
795
830
  def out_signature(self):
796
831
  return "(" + self.returns.signature + ")"
797
832
 
833
+ @cached_property
834
+ def dependency_interface(self):
835
+ deps = []
836
+ deps.extend(self.parameters.dependency_interface)
837
+ deps.extend(self.returns.dependency_interface)
838
+ return list(set(deps))
839
+
798
840
  class IdfSignal(IdfBase):
799
841
  def __init__(self, intf: IdfInterfaceBase, signal_data):
800
842
  super().__init__(intf, signal_data)
@@ -804,6 +846,10 @@ class IdfSignal(IdfBase):
804
846
  def signature(self):
805
847
  return "(" + self.properties.signature + ")"
806
848
 
849
+ @cached_property
850
+ def dependency_interface(self):
851
+ return self.properties.dependency_interface
852
+
807
853
  class IdfStructure(IdfBase):
808
854
  def __init__(self, intf: IdfInterfaceBase, stru_data, propety_key = "values"):
809
855
  super().__init__(intf, stru_data)
@@ -813,6 +859,10 @@ class IdfStructure(IdfBase):
813
859
  def signature(self):
814
860
  return "(" + self.values.signature+ ")"
815
861
 
862
+ @cached_property
863
+ def dependency_interface(self):
864
+ return self.values.dependency_interface
865
+
816
866
  def odf_schema(self):
817
867
  schema = {}
818
868
  for prop in self.values.parameters:
@@ -889,6 +939,10 @@ class IdfDictionary():
889
939
  else:
890
940
  return "a{" + self.key_obj.signature + self.values.signature + "}"
891
941
 
942
+ @cached_property
943
+ def dependency_interface(self):
944
+ return self.values.dependency_interface
945
+
892
946
  @property
893
947
  def key_is_string(self):
894
948
  return self.key_type in ["string", "signature", "object_path"]
@@ -967,13 +1021,51 @@ class IdfInterface(IdfInterfaceBase):
967
1021
  self.alias = None
968
1022
  self.load_elements()
969
1023
 
970
- @property
1024
+ @cached_property
1025
+ def dependency_idf_interface(self):
1026
+ deps: dict[str, IdfInterface] = {}
1027
+ intfs = self.dependency_interface
1028
+ for intf in intfs:
1029
+ intf_path = intf.replace(".", "/") + ".yaml"
1030
+ cwd = os.getcwd()
1031
+ realpath = None
1032
+ while cwd != "/":
1033
+ tmp_path = os.path.join(cwd, intf_path)
1034
+ if os.path.isfile(tmp_path):
1035
+ realpath = tmp_path
1036
+ break
1037
+ cwd = os.path.dirname(cwd)
1038
+
1039
+ if not realpath:
1040
+ raise FileNotFoundError(f"Dependency interface {intf} not exist")
1041
+ log.debug(f"Found dependency interface: {realpath}")
1042
+ deps[intf] = (IdfInterface(self.lookup, realpath))
1043
+ return deps
1044
+
1045
+ @cached_property
971
1046
  def signature(self):
972
1047
  sig = ""
973
1048
  for prop in self.properties:
974
1049
  sig += prop.signature
975
1050
  return "(" + sig + ")"
976
1051
 
1052
+ @cached_property
1053
+ def dependency_interface(self):
1054
+ deps = []
1055
+ for prop in self.properties:
1056
+ deps.extend(prop.dependency_interface)
1057
+ for _, dicti in self.dictionaries.items():
1058
+ deps.extend(dicti.dependency_interface)
1059
+ for _, strct in self.structures.items():
1060
+ deps.extend(strct.dependency_interface)
1061
+ for action in self.plugin.actions:
1062
+ deps.extend(action.dependency_interface)
1063
+ for signal in self.signals:
1064
+ deps.extend(signal.dependency_interface)
1065
+ for method in self.methods:
1066
+ deps.extend(method.dependency_interface)
1067
+ return list(set(deps))
1068
+
977
1069
  @property
978
1070
  def odf_schema(self):
979
1071
  schema = {}
@@ -1092,12 +1184,12 @@ class IdfInterface(IdfInterfaceBase):
1092
1184
  log.debug(f"{signal.name} signature: " + signal.signature)
1093
1185
  for method in self.methods:
1094
1186
  log.debug(f"{method.name} in signature: " + method.in_signature + ", out signature: " + method.out_signature)
1095
- for name, stru in self.structures.items():
1096
- log.debug(f"{name} signature: " + stru.signature)
1097
- for name, enum in self.enumerations.items():
1098
- log.debug(f"{name} signature: " + enum.signature)
1099
- for name, dictionary in self.dictionaries.items():
1100
- log.debug(f"{name} signature: " + dictionary.signature)
1187
+ # for name, stru in self.structures.items():
1188
+ # log.debug(f"{name} signature: " + stru.signature)
1189
+ # for name, enum in self.enumerations.items():
1190
+ # log.debug(f"{name} signature: " + enum.signature)
1191
+ # for name, dictionary in self.dictionaries.items():
1192
+ # log.debug(f"{name} signature: " + dictionary.signature)
1101
1193
  # 接口本身也是一个结构体
1102
1194
  intf_stru = IdfStructure(self, idf, propety_key="properties")
1103
1195
  self.structures[self.alias] = intf_stru
@@ -1,4 +1,7 @@
1
1
  #include "lb_base.h"
2
+ % for dep_intf in intf.dependency_interface:
3
+ #include "public/${dep_intf}.h"
4
+ % endfor
2
5
  #include "${intf.name}.h"
3
6
 
4
7
  <% class_name = intf.alias + "_Cli"
@@ -1,4 +1,7 @@
1
1
  #include "lb_base.h"
2
+ % for dep_intf in intf.dependency_interface:
3
+ #include "public/${dep_intf}.h"
4
+ % endfor
2
5
  #include "${intf.name}.h"
3
6
 
4
7
  <% class_name = intf.alias %>\
@@ -1,5 +1,8 @@
1
1
  <% from lbkit.codegen.ctype_defination import StringValidator %>\
2
2
  #include "lb_base.h"
3
+ % for dep_intf in intf.dependency_interface:
4
+ #include "public/${dep_intf}.h"
5
+ % endfor
3
6
  #include "${intf.name}.h"
4
7
 
5
8
  <%
@@ -71,7 +71,10 @@ class BuildComponent():
71
71
  self.pkg = None
72
72
  self.base_cmd = ""
73
73
  self.gen_conaninfo()
74
- self.base_cmd += f" --user {self.user} --channel {self.channel}"
74
+ # 此场景发布的包名不带@user/channel
75
+ if self.user != "litebmc" or self.channel != "release":
76
+ self.base_cmd += f" --user {self.user} --channel {self.channel}"
77
+
75
78
  self.base_cmd += f" -pr {self.profile} -s build_type={self.build_type} -r " + self.options.remote
76
79
  self.base_cmd += f" -pr:b {self.profile_build}"
77
80
  if self.options.cov:
@@ -126,8 +129,9 @@ class BuildComponent():
126
129
  self.name = pkg.get("name")
127
130
  self.version = pkg.get("version")
128
131
 
129
- self.package = self.name + "/" + self.version + \
130
- "@" + self.user + "/" + self.channel
132
+ self.package = self.name + "/" + self.version
133
+ if self.user != "litebmc" or self.channel != "release":
134
+ self.package += "@" + self.user + "/" + self.channel
131
135
  # 准备部署依赖
132
136
  requires = pkg.get("requires")
133
137
  deps = []
@@ -190,8 +194,12 @@ class BuildComponent():
190
194
  def build(self):
191
195
  log.info(os.getcwd())
192
196
 
193
- export_cmd = f"conan export . --user={self.user} --channel={self.channel}"
197
+ export_cmd = "conan export . "
198
+ if self.user != "litebmc" or self.channel != "release":
199
+ export_cmd += f"--user={self.user} --channel={self.channel}"
194
200
  tools.run(export_cmd, capture_output=False)
201
+ # import sys
202
+ # sys.exit(-1)
195
203
 
196
204
  lockfile = os.path.join(cwd, ".temp", "conan.lock")
197
205
  graphfile = os.path.join(cwd, ".temp", "graph.info")
@@ -28,8 +28,11 @@ libs = pkg.get("package_info", {}).get("libs", [])
28
28
  class LiteBmcConan(ConanFile):
29
29
  name = "${pkg_name}"
30
30
  version = "${pkg["version"]}"
31
+ % if pkg["user"] != "litebmc" or pkg["channel"] != "release":
32
+ ## @litebmc/release则生成的包名不带@user/channel
31
33
  user = "${pkg["user"]}"
32
34
  channel = "${pkg["channel"]}"
35
+ % endif
33
36
  settings = "os", "arch", "compiler", "build_type"
34
37
  description = "${pkg["description"]}"
35
38
  url = "${pkg["url"]}"
@@ -78,16 +81,12 @@ class LiteBmcConan(ConanFile):
78
81
  return
79
82
 
80
83
  scm_url = None
81
- remotes = git.run("remote -v")
82
- checked_name = []
83
- for r in remotes.splitlines():
84
- name, url = r.split(maxsplit=1)
85
- if name in checked_name:
86
- continue
87
- checked_name.append(name)
88
- url, scm_commit = git.get_url_and_commit(remote=name)
89
- if url.startswith("https://"):
90
- scm_url = url
84
+ scm_commit = git.get_commit()
85
+ branches = git.run("branch -r --contains {}".format(scm_commit))
86
+ remotes = git.run("remote")
87
+ for remote in remotes.splitlines():
88
+ if "{}/".format(remote) in branches:
89
+ scm_url = git.get_remote_url(remote)
91
90
  break
92
91
  if not scm_url:
93
92
  files.update_conandata(self, {"sources": {"commit": None, "url": None, "pwd": os.getcwd()}})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lbkit
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Tools provided by litebmc.com
5
5
  Home-page: https://www.litebmc.com
6
6
  Author: xuhj@litebmc.com
@@ -1,2 +0,0 @@
1
-
2
- __version__ = '0.6.2'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes