# V7.9.x Version Control Workaround?

**URL:** <https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468>\
**Category:** Ignition\
**Tags:** ignition79, scripting\
**Created:** [February 16, 2021, 5:05pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468 "2021-02-16T17:05:42Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmaynes](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmaynes/32/6852_2.png) [@cmaynes](https://forum.inductiveautomation.com/u/cmaynes)\
**Post date:** [February 16, 2021, 5:05pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/1 "2021-02-16T17:05:42Z")

</div>

I know version control will not be coming to v.7.9.x, but I need a workaround so I can use it. I cannot move my system to v8.x due to the cost of rework and testing.

Does anyone either have an Ignition module or a jython/python script to handle expanding a .proj file into folders and files?

If not, does anyone know how to decode the sections in the **.proj** files?  
For decoding the , I have the following so far but the header and footer remain encoded and there is not a consistent pattern or position to just remove them.

```python
import zlib
import base64

string = '<bytes> from a .proj file'
decoded = base64.b64decode(string)
unzipped = zlib.decompress(decoded , 16 + zlib.MAX_WBITS)

```

current example output:

```auto
b'\x98)\x8f\xaaC\xf7JO\xb2\x8d\xca<H\x96\xaf\xc9\x00\x00\x00\x02\x00\x00\x01v\xf8\xc9@\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x07\x00\x00\x03str\x00\x00\x00\x02\x00\x00\x107.9.6.2018012914\x00\x00\x00\x04\x00\x00\x079.9.6.0\x00\x00\x00\x01\x00\x00\x11framework.version\x00\x00\x00\x00\x00\x00\x07objects\x00\x00\x00\x03\x00\x00\x0cfpmi.version\x00\x00\x00\x08\x00\x05\xe7"""Module for configuring the ORM model for constants.\n\nWARNING: Due to recursion problem with everything importing this module,\nuser id is not automatically pulled in. Any updates to this table need\nto manually handle updating the user. Not a real problem, because updates\nto this table should never really by through app layer.\n"""\n\nimport datetime\n\nfrom shared.orm import *\n\n __all__ = [\n\t\'Constant\',\n]\n\n\ndef change_updated_and_updated_by(table, indices):\n\tif \'updated\' in table.cols.aliases:\n\t\ttable[indices, \'updated\'] = datetime.datetime.now()\n\n\nclass Constant(DatabaseTable):\n\tconnection_name = \'NDB\'\n\talias = \'constant\'\n\tname = \'Constant\'\n\tschema = \'aut_portal\'\n\t\n\tconstant_id = Col(\'ConstantId\')\n\tgroup = Col(\'Group\')\n\tsubgroup = Col(\'Subgroup\')\n\tcode = Col(\'Code\')\n\tvalue = Col(\'Value\')\n\tdesc = Col(\'Description\')\n\tunits = Col(\'Units\')\n\tdtype = Col(\'DataType\', \'varchar\')\n\tmax_length = Col(\'MaxLength\')\n\tcreated = Col(\'CreatedDateTime\', datetime.datetime.now, False)\n\tcreated_by = Col(\'CreatedByUserId\', None, False)\n\tupdated = Col(\'UpdatedDateTime\', datetime.datetime.now)\n\tupdated_by = Col(\'UpdatedByUserId\', None)\n\t\n\tafter_update = [change_updated_and_updated_by]\n\tunique_record_columns = [\n\t\t(\'group\', \'subgroup\', \'code\',),\n\t]\n\tdefault_order = [\n\t\t\'group\', \'subgroup\', \'code\'\n\t]\n\t\n\tdefault_insert_cache_columns = [\'constant_id\']\n\tdefault_insert_keys = [\'group\', \'subgroup\', \'code\']\n\t\n\tdefault_update_cache_columns = []\n\tdefault_update_keys = [\'constant_id\']\n\n\tdefault_delete_keys = [\'constant_id\']\n\x00\x00\x00\x05\x00\x00\ttimestamp\x00\x00\x00\x06\x00\x00\x1cTue Jan 12 17:48:27 EST 2021\x18\x00\x00\x00\x00\x03\x00\x00\x00\x01\x08\x00\x00\x00\x02\x00\x00\x00\x03\x08\x00\x00\x00\x04\x00\x00\x00\x05\x08\x00\x00\x00\x06\x00\x00\x00\x01 \x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x08'

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 16, 2021, 5:20pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/2 "2021-02-16T17:20:47Z")

</div>

TL/DR: Not possible for anyone outside IA, and not possible at all if any 3rd party modules generate their own resources.

Project files can contain all kinds of serialized resources, with the binary encoding defined by the Ignition module (including 3rd parties) that generated them. Some of the encodings expand to exotic XML with _recursively_ nested binary encodings. All of the encodings depend on the serialization technology chosen by the module author(s).

This is still true in v8+ for Vision and a variety of other resources, but the binary content is at least broken out into folders for a slightly improved VCS experience.

There is no work-around. In my not-so-humble opinion, it _ **cannot** _ be done. If you must have your projects in a VCS, upgrade. Even after upgrading, be prepared for your VCS experience with Vision resources to be somewhat unsatisfying.

---

<div class="post-metadata">

**Author:** ![cmaynes](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmaynes/32/6852_2.png) [@cmaynes](https://forum.inductiveautomation.com/u/cmaynes)\
**Post date:** [February 16, 2021, 5:29pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/3 "2021-02-16T17:29:20Z")

</div>

I have been wandering around their java docs trying to find something to decode the project and shared scripts, which are the only things I am interested in. I accept the other project resources (windows, templates, etc.) will be blobs pretty much.

As far as you know, is there any library/interface in their system which can decode project resources to get the scripts they contain as strings?

Presumably they have to have this somewhere because they do it in the designer, but I cannot find anything.

Thanks in advance for any clarity you can provide.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 16, 2021, 5:44pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/4 "2021-02-16T17:44:51Z")

</div>

Sorry, no.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [February 16, 2021, 6:38pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/5 "2021-02-16T18:38:51Z")

</div>

> [@cmaynes](#):
>
> As far as you know, is there any library/interface in their system which can decode project resources to get the scripts they contain as strings?

Look at the `XMLDeserializer` you can create from a `DesignerContext` instance; that would be your entrypoint to decoding project resources.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 16, 2021, 6:47pm UTC](https://forum.inductiveautomation.com/t/v7-9-x-version-control-workaround/43468/6 "2021-02-16T18:47:52Z")

</div>

> [@paul-griffith](#):
>
> XMLDeserializer

Hmmm.. I vaguely remember that. I had to create and register one when implementing my `TransientDataset`.
