Switching to the New Module Library

Success! Many thanks. This is going to be a great improvement once everyone gets the hang of it. If I can make it work, anyone can do it. Consider me your least common denominator.

Although I am somewhat divorced from the old page now at Great Battles of Alexander: Deluxe Edition - Module Library - Vassal, if you need suggestions for that page I can offer that up, but I think that makes Tim M. the primary module holder for that era of the game. If you need to remove my module versions from that page, that is ok to do so, or I will do so once those controls are allowed for users.

Perhaps a few more words would be in order, assuming this in response to @Vorchek

On your project page: https://vassalengine.org/library/projects/El_Alamein_Battles_in_North_Africa_1942, you have FontAwesome-Cubes-icon and Packages. Clicking the + next to that adds a new Package.

Packages is a set of - versioned - files that go together. For example, a module and save files. Typically, you only need one package called, say Module.

If you create a package called Module, you will have FontAwesome-Cube-icon and Module. If you click on the + next to that, you can create a Release.

The releases are numbers according to semantic versioning, i.e.,

  • major.minor.patch where major, minor, and patch are whole numbers and all are mandatory.

If you create a release, say 1.0.0, then you will have a green rectangle with rounded corners with the release number inside. Next to that is a +. If you press that, then you can upload a file to that release. Note, your .vmod file must have a version number that follows semantic versioning.

Yours,
Christian

I could swear I’m following these instructions to the letter, but I get this:


I tried variations of the file name–putting the numbers in front, leaving out periods, etc.–yet this is the result every time. Of course I’m aware that the top package (1.0.0) is null and void, which I can’t get rid of at the moment. But the module package: what am I missing?

Check the version number saved inside the module. What is it?

1 Like

I’ve added a welcome page for the library.

1 Like

“Inside the module” !!! And that had already been pointed out, too. IT WORKS NOW. Yay!

Hi all,

A lot of you have problems with the version number in the VASSAL module. The obvious thing is to open up the module in the VASSAL editor and change it there. In some circumstances, that is unattractive as it will upgrade the module to the version of VASSAL that you are currently running.

To address that, I’ve developed a small script that only changes the version number in the module. That is all it does - no other data is changed.

To use it, do

  1. You must have Python installed - see the link for installation instructions on various platforms.

  2. Install the package pywargame:

    $ pip install pywargame 
    
  3. Copy the below code to a file, say update_version.py and save

    Code to copy (use the copy button on the top-right)

    #!/usr/bin/env python
    
    from pywargame.vassal import VMod
    
    def update(file, new_version, verbose, showold):
        from semver import parse
        from sys import stderr
        
        try:
            v = parse(new_version)
        except Exception as e:
            print(f'Version string {new_version} not valid: {e}',
                  file=stderr)
            return
    
        def patch(build,module,vmod,verbose):
            game    = build.getGame()
            title   = game['name']
            version = game['version']
            do      = 'Will update ' if showold else "Updating"
            print(f'{do} version of "{title}" from {version} to {new_version}')
            if not showold:
                game['version'] = new_version
    
            data    = module.getData()
            version = data.getVersion()[0]
            title   = data.getName()[0]
            print(f'{do} version of "{title.getText()}" '
                  f'from {version.getText()} to {new_version}')
            if not showold:
                version.setText(new_version)
    
            if not showold:
                print(f'Now {game["version"]} {data.getVersion()[0].getText()}')
    
    
            if showold:
                raise SystemExit()
                
                
        VMod.patchFunction(file,patch,verbose)
    
    
    if __name__ == '__main__':
        from argparse import ArgumentParser, FileType
    
        ap = ArgumentParser(description='Update versionnumber in VMod')
        ap.add_argument('input', type=FileType('r'),help='Input file')
        ap.add_argument('version',type=str,help='New version number',
                        default='1.0.0')
        ap.add_argument('--verbose','-v',action='store_true',
                        help='Be verbose')
        ap.add_argument('--show','-s',action='store_true',
                        help='Show current version in module')
    
        args = ap.parse_args()
    
        filename = args.input.name
        args.input.close()
    
        update(filename, args.version, args.verbose, args.show)
    
    # EOF
    
  4. Change persmissions to be executable

    $ chmod a+x update_version.py
    
  5. Execute as

    $ ./update_version.py MyModule.vmod 1.2.3
    

    where MyModule.vmod is your module file, and 1.2.3 is the version number to set in the module.

    The given version number is checked to see if it is a valid semantic version.

    You can pass the option --show to only see what the current version is. Note that the vers

Hope that’s helpful.

Yours,
Christian

1 Like

So, I guess I’ve finally gotten a handle on project creation. That feels good; like riding a bicycle, easy once you’ve done it. Before I create any more, I want to get my house in order: meaning, to straighten out, fix, update all my old modules (aka projects). That signifies being able to change, upgrade, delete items (such as unwanted releases) on an “owned” page. I’m in no hurry, and still not clear how much will remain in the hands of the administrator, but I’ll be keen to learn how those aspects develop. If and when that comes, I’ll be ready. The new library will really advance.

1 Like

I’ve split these pages into separate projects, as detailed below.

The Auto-generated project has been labeled as obsolete, and they, the auto-generated projects, can be deleted.

Note, I’ve added screenshots to the release entries, so as to preserve them. Later on, they can be moved to a proper gallery, when that is possible through the front-end.

Yours,
Christian

1 Like

I’m working on adding more useful error messages now.

I had said above not to reupload files, because doing that doesn’t preserve file history. Now I will have to fix all of these.

Please, please, please DO NOT REUPLOAD FILES when splitting pages. Tell me what you want moved and I will move the files.

Why do many of the newly uploaded Module Versions to the NEW Module Library NOT have a Vassal Configuration Reference on the New Module Library Pages, while Older Module Versions that succesfuly Migrated to the New Pages Retain their Vassal Configuration Reference?

My bad…I assume. Didn’t see the original message not to do so.

I think Joel’s message was meant for me, so I think you’re good :slight_smile:

Like @clanmacrae I do not think I’ve seen that message. Can you point to that message, just out of curiosity?

Anyways, I see your point of “preserve file history” which I take to mean that the upload data is not the original upload date.

How about I provide you with a mapping from file name to original upload date, which you can then use to modify the SQL table(s)? Would that make it easier? In that way, you won’t need to do too much on the back-end side.

Yours,
Christian

1 Like

Joel said it in a reply to me much earlier in the thread (post #36). Not too surprising if people missed it.

1 Like

Ah:

This I fixed by the above Python script - a simple solution that didn’t bother admins and forced the old modules into the new schema - a win-win, I think :slight_smile:

Rather vague, I think - probably why it got missed.

Any case, @uckelman, below is a JSON array of the files that would need their DB entry “fixed”.

{
  "Afrika Korps": [
    [
      {
        "filename": "AFK-2.3.1.vmod",
        "date": "2020-05-07",
        "size": "3.1MB",
        "compatibility": "3.2.17",
        "maintainers": [
          {
            "name": "WGA",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "Bill Thomson",
            "address": "bill@wargameacademy.org"
          }
        ]
      },
      {
        "filename": "AFK-2.3.vmod",
        "date": "2020-05-07",
        "size": "3.1MB",
        "compatibility": "3.2.17",
        "maintainers": [
          {
            "name": "WGA",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "Bill Thomson",
            "address": "bill@wargameacademy.org"
          }
        ]
      },
      {
        "filename": "AFKv222.vmod",
        "date": "2010-03-08",
        "size": "3259363",
        "compatibility": "3.1.12",
        "maintainers": [
          {
            "name": "WGA",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "jw62",
            "address": "jaw1362@windstream.net"
          },
          {
            "name": "Brent Easton",
            "address": "b.easton@exemail.com.au"
          },
          {
            "name": "tcrow",
            "address": "tim_a_crowley@yahoo.com"
          }
        ]
      }
    ],
    [
      {
        "filename": "Afrika_Korps_REV_Map_1.01.vmod",
        "date": "2024-03-25",
        "size": "7.59 MB",
        "compatibility": "3.2.17",
        "maintainers": [
          {
            "name": "Allen Dickerson",
            "address": "allendkrsn@yahoo.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "Afrika_Korps2_1.1.1.vmod",
        "date": "2014-06-30",
        "size": "2.21MB",
        "compatibility": "3.2.11+",
        "maintainers": [
          {
            "name": "Alex Carmel",
            "address": "acv@miniguru.ca"
          }
        ],
        "contributors": [
          {
            "name": "Charles McLellan",
            "address": "cgmclellan2000@knology.net"
          }
        ]
      }
    ],
    [
      {
        "filename": "Afrika_Korps2.vmod",
        "date": "2010-10-04",
        "size": "2.21MB",
        "compatibility": "3.1.14+",
        "maintainers": [
          {
            "name": "Charles McLellan",
            "address": "cgmclellan2000@knology.net"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "Afrika_Korps_Documents.zip",
        "date": "2010-10-18",
        "size": "5.23 MB",
        "compatibility": "n/a",
        "maintainers": [
          {
            "name": "Charles McLellan",
            "address": "cgmclellan2000@knology.net"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "AfrikaKorps-1.1-ch.vmod",
        "date": "2022-12-05",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "AfrikaKorps-1.1-ch-oldschool.vmod",
        "date": "2022-12-05",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "AfrikaKorps-2.0-ch.vmod",
        "date": "2023-02-12",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "AfrikaKorps-2.0-ch-oldschool.vmod",
        "date": "2023-02-12",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "AfrikaKorps-2.1-ch.vmod",
        "date": "2024-02-06",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "AfrikaKorps-2.1-ch-oldschool.vmod",
        "date": "2024-02-06",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ]
  ],
  "Anzio Beachhead": [
    [
      {
        "filename": "Anzio_Beachhead_v1.1.vmod",
        "date": "2021-10-31",
        "size": "2.33 MB",
        "compatibility": "VASSAL 3.5.8",
        "maintainers": [],
        "contributors": []
      }
    ]
  ],
  "Battle for Moscow": [
    [
      {
        "filename": "BattleforMoscow.vmod",
        "date": "2005-09-30",
        "size": "",
        "compatibility": "2.1",
        "maintainers": [],
        "contributors": []
      }
    ],
    [
      {
        "filename": "BFM.vmod",
        "date": "2011-04-06",
        "size": "",
        "compatibility": "3.1.12",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "BFM-1.0.2.vmod",
        "date": "2021-10-21",
        "compatibility": "3.5",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "BFM-1.0.3.vmod",
        "date": "2022-08-14",
        "compatibility": "3.5",
        "maintainers": [],
        "contributors": []
      }
    ],
    [
      {
        "filename": "BattleForMoscow-ch-1.0.vmod",
        "date": "2023-01-23",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "BFM-1.0.1.vmod",
        "date": "2021-03-05",
        "compatibility": "3.5",
        "maintainers": [
          {
            "name": "Olivier",
            "address": "olivier@oberlabs.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "Battle_for_Moscow_Expan_and_Winter_Off_2.0.vmod",
        "date": "2022-05-10",
        "compatibility": "3.5",
        "maintainers": [
          {
            "name": "json99",
            "address": "drj@comhem.se"
          }
        ],
        "contributors": [
          {
            "name": "json99",
            "address": "drj@comhem.se"
          },
          {
            "name": "Olivier",
            "address": "olivier@oberlabs.com"
          },
          {
            "name": "Davejm",
            "address": "dave_j_march@yahoo.co.uk"
          }
        ]
      }
    ]
  ],
  "Battle: The Game of Generals": [
    [
      {
        "filename": "Battle.vmod",
        "date": "2002-12-18",
        "size": "",
        "compatibility": "?",
        "maintainers": [
          {
            "name": "Skalla",
            "address": "Skalla@mailinator.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "Battle-1.0-ch.vmod",
        "date": "2023-03-28",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ]
  ],
  "D-Day": [
    [
      {
        "filename": "D-Day-v3.0a.vmod",
        "date": "2023-11-14",
        "size": "",
        "compatibility": "3.7.5",
        "maintainers": [
          {
            "name": "Frank Jordan",
            "address": "woody8297@yahoo.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "DDay-1.0-ch.vmod",
        "date": "2022-10-28",
        "size": "",
        "compatibility": "3.6.7",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "DDay-1.0-ch-oldschool.vmod",
        "date": "2022-10-28",
        "size": "",
        "compatibility": "3.6.7",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "D-DAY-77-1.1.vmod",
        "date": "2018-08-04",
        "size": "",
        "compatibility": "3.2.17",
        "maintainers": [
          {
            "name": "Tommy Crispin",
            "address": "tommycrispin@gmail.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "DDayVolkssturm.vmod",
        "date": "2021-08-26",
        "compatibility": "3.5.7",
        "maintainers": [
          {
            "name": "Gordon Cerow",
            "address": "Gcerow@cs.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "D-Day-v202.vmod",
        "date": "2010-03-21",
        "size": "3276055",
        "compatibility": "3.1.14",
        "maintainers": [
          {
            "name": "Brian Mason",
            "address": "brian4482@gmail.com"
          }
        ],
        "contributors": [
          {
            "name": "BiLL Soz",
            "address": "BiLLSoz@comcast.net"
          }
        ]
      },
      {
        "filename": "D-Day.vmod",
        "date": "2009-11-02",
        "size": "3166984",
        "compatibility": "3.1.12",
        "maintainers": [
          {
            "name": "Brian Mason",
            "address": "brian4482@gmail.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "D-Day_Windows_Desktop_Icons.zip",
        "date": "",
        "size": "2499092",
        "compatibility": "n/a",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "Using_the_D-Day_Module.pdf",
        "date": "",
        "size": "unzip",
        "compatibility": "n/a",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "TAHGC_D-Day_Rulebook-100313.pdf",
        "date": "",
        "size": "4720721",
        "compatibility": "n/a",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "D-Day_Basic_Game_Rules_1965_edition.pdf",
        "date": "",
        "size": "1310354",
        "compatibility": "n/a",
        "maintainers": [],
        "contributors": []
      },
      {
        "filename": "D-Day_Tournament_Rules_1965_edition.pdf",
        "date": "",
        "size": "4063203",
        "compatibility": "n/a",
        "maintainers": [],
        "contributors": []
      }
    ]
  ],
  "Gettysburg: 125th Anniversary Edition": [
    [
      {
        "filename": "G88v33b10.vmod",
        "date": "2013-04-16",
        "size": "",
        "compatibility": "3.1.20",
        "maintainers": [
          {
            "name": "Bill Thomson(wga)",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "jw62",
            "address": "jaw1362@windstream.net"
          },
          {
            "name": "swampwallaby",
            "address": "b.easton@exemail.com.au"
          }
        ]
      },
      {
        "filename": "G88v33b11.vmod",
        "date": "2016-07-17",
        "size": "",
        "compatibility": "3.1.20",
        "maintainers": [
          {
            "name": "Bill Thomson(wga)",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "jw62",
            "address": "jaw1362@windstream.net"
          },
          {
            "name": "swampwallaby",
            "address": "b.easton@exemail.com.au"
          }
        ]
      },
      {
        "filename": "G88v34.vmod",
        "date": "2021-04-11",
        "size": "",
        "compatibility": "3.1.27",
        "maintainers": [
          {
            "name": "Bill Thomson(wga)",
            "address": "bill@wargameacademy.org"
          }
        ],
        "contributors": [
          {
            "name": "jw62",
            "address": "jaw1362@windstream.net"
          },
          {
            "name": "swampwallaby",
            "address": "b.easton@exemail.com.au"
          }
        ]
      }
    ],
    [
      {
        "filename": "Campaign-130405.vsav",
        "date": "2013-04-02",
        "size": "",
        "compatibility": "3.1.20",
        "maintainers": [],
        "contributors": []
      }
    ],
    [
      {
        "filename": "GettysburgSmithsonian-1.0.vmod",
        "date": "2023-07-15",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "GettysburgSmithsonian-1.1.vmod",
        "date": "2023-08-06",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      },
      {
        "filename": "GettysburgSmithsonian-1.2.vmod",
        "date": "2024-02-05",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ]
  ],
  "Napoleon at Waterloo": [
    [
      {
        "filename": "NapoleonAtWaterloo-1.0-ch.vmod",
        "date": "2024-04-25",
        "size": "",
        "compatibility": "3.6",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "Napoleon at Waterloo SPI V1.0.vmod",
        "date": "22-04-03",
        "size": "",
        "compatibility": "3.5.8",
        "maintainers": [
          {
            "name": "Davejm",
            "address": "dave_j_march@yahoo.co.uk"
          }
        ],
        "contributors": [
          {
            "name": "iam2509",
            "address": "stephen.oliver439@yahoo.com"
          }
        ]
      }
    ],
    [
      {
        "filename": "Napoleon at Waterloo 2nd Ed Vers 2.2.vmod",
        "date": "2021-08-01",
        "size": "",
        "compatibility": "3.5.3",
        "maintainers": [
          {
            "name": "Stephen Oliver",
            "address": "stephen.oliver439@yahoo.com"
          }
        ],
        "contributors": [
          {
            "name": "iam2509",
            "address": "stephen.oliver439@yahoo.com"
          }
        ]
      }
    ]
  ],
  "PanzerArmee Afrika: Rommel in the Desert, April 1941 - November 1942": [
    [
      {
        "filename": "PanzerArmeeAfrika(SPI-AH)_v132.vmod",
        "date": "2024-08-10",
        "size": "",
        "compatibility": "3.7.13",
        "maintainers": [],
        "contributors": [
          {
            "name": "Luc Liu",
            "address": "lucliu@live.com"
          }
        ]
      },
      {
        "filename": "PanzerArmeeAfrika(SPI-AH)_v131.vmod",
        "date": "2024-06-30",
        "size": "",
        "compatibility": "3.7.12",
        "maintainers": [],
        "contributors": [
          {
            "name": "Luc Liu",
            "address": "lucliu@live.com"
          }
        ]
      },
      {
        "filename": "PanzerArmeeAfrika(SPI-AH)_v130.vmod",
        "date": "2024-06-10",
        "size": "",
        "compatibility": "3.7.12",
        "maintainers": [],
        "contributors": [
          {
            "name": "Luc Liu",
            "address": "lucliu@live.com"
          }
        ]
      },
      {
        "filename": "PanzerArmeeAfrika(SPI-AH).vmod",
        "date": "2021-03-15",
        "size": "",
        "compatibility": "3.5.2",
        "maintainers": [],
        "contributors": [
          {
            "name": "Luc Liu",
            "address": "lucliu@live.com"
          }
        ]
      },
      {
        "filename": "PanzerArmeeAfrika_v32.vmod",
        "date": "2021-03-15",
        "size": "",
        "compatibility": "3.5.2",
        "maintainers": [],
        "contributors": [
          {
            "name": "Luc Liu",
            "address": "lucliu@live.com"
          }
        ]
      }
    ]
  ],
  "The Battle of Agincourt": [
    [
      {
        "filename": "BoA_100.vmod",
        "date": "2016-10-16",
        "size": "",
        "compatibility": "3.2.16",
        "maintainers": [
          {
            "name": "KevOs4",
            "address": "terry.e.gordon@gmail.com"
          }
        ],
        "contributors": [
          {
            "name": "KevOs4",
            "address": "terry.e.gordon@gmail.com"
          }
        ]
      },
      {
        "filename": "BoA_Notes.txt",
        "date": "2016-10-16",
        "size": "",
        "compatibility": "",
        "maintainers": [
          {
            "name": "KevOs4",
            "address": "terry.e.gordon@gmail.com"
          }
        ],
        "contributors": [
          {
            "name": "KevOs4",
            "address": "terry.e.gordon@gmail.com"
          }
        ]
      }
    ]
  ],
  "The Drive on Metz, 1944": [
    [
      {
        "filename": "metzv1.vmod",
        "date": "2010-07-04",
        "size": "",
        "compatibility": "3.0.17",
        "maintainers": [
          {
            "name": "Davout",
            "address": "mbeninger@videotron.ca"
          }
        ],
        "contributors": []
      }
    ],
    [
      {
        "filename": "DriveOnMetz-1.0-ch.vmod",
        "date": "2023-07-31",
        "size": "",
        "compatibility": "3.6+",
        "maintainers": [
          {
            "name": "Christian Holm Christensen",
            "address": "cholmcc@gmail.com"
          }
        ],
        "contributors": []
      }
    ]
  ]
}

Sorry for the length - just a lot of data, and the forum doesn’t like attaching anything but images.

Yours,
Christian

Oh, and while I’m at it, here’s the data to move images from package revisions to galleries.

{
  "afrika_korps_wga": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "AFK-2.3.gif": {
          "url": "https://obj.vassalengine.org/gls/1/1/AFK-2.3.gif",
          "published_at": "2025-06-17T21:58:03.683248349Z",
          "published_by": "cholmcc"
        },
        "AFK-2.3.png": {
          "url": "https://obj.vassalengine.org/gls/d/6/AFK-2.3.png",
          "published_at": "2025-06-17T21:55:59.917629744Z",
          "published_by": "Cholmcc"
        },
        "AFKv222.png": {
          "url": "https://obj.vassalengine.org/gls/8/4/AFKv222.png",
          "published_at": "2025-06-17T21:55:44.190627445Z",
          "published_by": "Cholmcc"
        }
      }
    }
  },
  "afrika_korps_stiglr": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "Afrika_Korps_REV_Map_1.01.png": {
          "url": "https://obj.vassalengine.org/gls/2/d/Afrika_Korps_REV_Map_1.01.png",
          "published_at": "2025-06-17T21:59:07.559071088Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "afrika_korps_cgmclellan": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "Afrika_Korps2.png": {
          "url": "https://obj.vassalengine.org/gls/f/9/Afrika_Korps2.png",
          "published_at": "2025-06-17T21:54:10.247249124Z",
          "published_by": "cholmcc"
        },
        "Afrika_Korps2_1.0.1.png": {
          "url": "https://obj.vassalengine.org/gls/4/8/Afrika_Korps2_1.0.1.png",
          "published_at": "2025-06-17T21:53:20.596718130Z",
          "published_by": "cholmcc"
        },
        "Afrika_Korps2_1.0.1_alt.png": {
          "url": "https://obj.vassalengine.org/gls/1/9/Afrika_Korps2_1.0.1_alt.png",
          "published_at": "2025-06-17T21:53:39.716125327Z",
          "published_by": "cholmcc"
        },
        "Afrika_Korps2_1.0.1_full.png": {
          "url": "https://obj.vassalengine.org/gls/4/a/Afrika_Korps2_1.0.1_full.png",
          "published_at": "2025-06-17T21:53:58.825449524Z",
          "published_by": "cholmcc"
        },
        "Afrika_Korps2_1.1.1.png": {
          "url": "https://obj.vassalengine.org/gls/a/4/Afrika_Korps2_1.1.1.png",
          "published_at": "2025-06-17T21:54:22.840912887Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "afrika_korps_cholmcc": {},
  "anzio_beachhead_unknown": {},
  "anzio_beachhead_cholmcc": {
    "Module": {
      "1.0.1": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/4/f/vassal.png",
          "published_at": "2025-06-18T09:33:49.025295223Z",
          "published_by": "cholmcc"
        },
        "vassal_combat_2_declare.png": {
          "url": "https://obj.vassalengine.org/gls/1/0/vassal_combat_2_declare.png",
          "published_at": "2025-06-18T09:34:07.094762029Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "battle_skalla": {
    "Module": {
      "1.1.0": {
        "BattleScreen.gif": {
          "url": "https://obj.vassalengine.org/gls/d/a/BattleScreen.gif",
          "published_at": "2025-06-18T09:47:51.615813826Z",
          "published_by": "Uckelman"
        }
      }
    }
  },
  "battle_cholmcc": {
    "Module": {
      "1.0.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/3/d/vassal.png",
          "published_at": "2025-06-18T09:53:43.289006061Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "battle_for_moscow_operation_typhoon_olivier": {
    "Module": {
      "1.0.3": {
        "BFM-1.0.3.png": {
          "url": "https://obj.vassalengine.org/gls/6/8/BFM-1.0.3.png",
          "published_at": "2025-06-18T16:35:02.908697530Z",
          "published_by": "Cholmcc"
        }
      }
    }
  },
  "battle_for_moscow_operation_typhoon_expansion_json99": {
    "Module": {
      "2.0.0": {
        "Battle_for_Moscow_Expan_and_Winter_Off_2.0.png": {
          "url": "https://obj.vassalengine.org/gls/1/c/Battle_for_Moscow_Expan_and_Winter_Off_2.0.png",
          "published_at": "2025-06-18T16:59:16.772936218Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "battle_for_moscow_unknown": {
    "Module": {
      "1.2.0": {
        "BattleforMoscow.png": {
          "url": "https://obj.vassalengine.org/gls/8/7/BattleforMoscow.png",
          "published_at": "2025-06-18T17:09:03.828413954Z",
          "published_by": "Cholmcc"
        }
      }
    }
  },
  "battle_for_moscow_cholmcc": {
    "Module": {
      "1.2.2": {
        "vassal-declare.png": {
          "url": "https://obj.vassalengine.org/gls/b/9/vassal-declare.png",
          "published_at": "2025-06-18T18:18:12.902063659Z",
          "published_by": "cholmcc"
        },
        "vassal-resolve.png": {
          "url": "https://obj.vassalengine.org/gls/b/1/vassal-resolve.png",
          "published_at": "2025-06-18T18:18:23.671409478Z",
          "published_by": "cholmcc"
        },
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/d/e/vassal.png",
          "published_at": "2025-06-18T18:18:03.289884982Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "d_day_2nd_ed_brian448": {
    "Modules": {
      "2.0.2": {
        "D-Day_Screen_Shot.jpg": {
          "url": "https://obj.vassalengine.org/gls/0/7/D-Day_Screen_Shot.jpg",
          "published_at": "2025-06-18T12:42:46.531717624Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "d_day_3rd_ed_crispy1critter": {},
  "d_day_3rd_ed_woody8297": {
    "Module": {
      "3.0.0": {
        "D-Day_3.0a_Camo_counters.jpg": {
          "url": "https://obj.vassalengine.org/gls/8/8/D-Day_3.0a_Camo_counters.jpg",
          "published_at": "2025-06-18T12:48:43.077345193Z",
          "published_by": "cholmcc"
        },
        "D-Day_3.0a_pic.jpg": {
          "url": "https://obj.vassalengine.org/gls/3/f/D-Day_3.0a_pic.jpg",
          "published_at": "2025-06-18T12:48:52.656312516Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "d_day_3rd_ed_cholmcc": {
    "Colourful": {
      "1.1.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/d/1/vassal.png",
          "published_at": "2025-06-18T13:13:22.459384583Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "gettysburg_125th_anniversary_wga": {
    "Module": {
      "3.4.0": {
        "G88screenShot.gif": {
          "url": "https://obj.vassalengine.org/gls/5/e/G88screenShot.gif",
          "published_at": "2025-06-18T11:51:10.515025952Z",
          "published_by": "Uckelman"
        },
        "G88v34-game-example-USA14.png": {
          "url": "https://obj.vassalengine.org/gls/8/e/G88v34-game-example-USA14.png",
          "published_at": "2025-06-18T11:50:58.708114540Z",
          "published_by": "Wga"
        },
        "Screenshot.gif": {
          "url": "https://obj.vassalengine.org/gls/1/5/Screenshot.gif",
          "published_at": "2025-06-18T11:51:21.002272201Z",
          "published_by": "Uckelman"
        }
      }
    }
  },
  "gettysburg_125th_anniversary_cholmcc": {
    "Module": {
      "1.3.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/d/7/vassal.png",
          "published_at": "2025-06-18T12:05:46.820440973Z",
          "published_by": "cholmcc"
        },
        "vassal_detail.png": {
          "url": "https://obj.vassalengine.org/gls/e/2/vassal_detail.png",
          "published_at": "2025-06-18T12:05:57.377497223Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "napoleon_at_waterloo_2nd_ed_stephen_oliver": {
    "Module": {
      "2.2.0": {
        "NapAtWtrloo.jpg": {
          "url": "https://obj.vassalengine.org/gls/7/0/NapAtWtrloo.jpg",
          "published_at": "2025-06-18T11:01:04.651304611Z",
          "published_by": "Kiev"
        }
      }
    }
  },
  "napoleon_at_waterloo_3rd_ed_davejm": {
    "Module": {
      "1.1.0": {
        "Board1a.png": {
          "url": "https://obj.vassalengine.org/gls/a/7/Board1a.png",
          "published_at": "2025-06-18T11:13:18.504812534Z",
          "published_by": "cholmcc"
        }
      },
      "1.0.0": {
        "Board1.png": {
          "url": "https://obj.vassalengine.org/gls/c/3/Board1.png",
          "published_at": "2025-06-18T11:12:12.557263085Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "napoleon_at_waterloo_cholmcc": {
    "Module": {
      "1.1.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/9/5/vassal.png",
          "published_at": "2025-06-18T11:31:53.933178296Z",
          "published_by": "cholmcc"
        },
        "vassal_detail.png": {
          "url": "https://obj.vassalengine.org/gls/0/6/vassal_detail.png",
          "published_at": "2025-06-18T11:32:05.642951878Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "panzerarmee_afrika_gamer94501": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "PanzerarmeeAfrika-001e.png": {
          "url": "https://obj.vassalengine.org/gls/c/e/PanzerarmeeAfrika-001e.png",
          "published_at": "2025-06-18T07:24:20.635723863Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "panzerarmee_afrika_william_hay_spi": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "PzArmSPIandAH.jpg": {
          "url": "https://obj.vassalengine.org/gls/7/c/PzArmSPIandAH.jpg",
          "published_at": "2025-06-18T07:12:06.874168920Z",
          "published_by": "Kiev"
        },
        "PzArmSPImap.jpg": {
          "url": "https://obj.vassalengine.org/gls/5/8/PzArmSPImap.jpg",
          "published_at": "2025-06-18T07:12:19.894898902Z",
          "published_by": "Kiev"
        }
      }
    }
  },
  "panzerarmee_afrika_luc_liu": {
    "Screenshots": {
      "0.0.0-screenshots": {
        "PAA_vmod_v132.png": {
          "url": "https://obj.vassalengine.org/gls/1/0/PAA_vmod_v132.png",
          "published_at": "2025-06-18T07:39:02.386199624Z",
          "published_by": "cholmcc"
        },
        "PanzerArmeeAfrika(SPI-AH)_v130.png": {
          "url": "https://obj.vassalengine.org/gls/0/5/PanzerArmeeAfrika(SPI-AH)_v130.png",
          "published_at": "2025-06-18T07:38:49.176176719Z",
          "published_by": "cholmcc"
        },
        "PanzerarmeeAfrika-SPI-AH-1.3.5.png": {
          "url": "https://obj.vassalengine.org/gls/5/9/PanzerarmeeAfrika-SPI-AH-1.3.5.png",
          "published_at": "2025-06-18T07:39:14.712292618Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "panzerarmee_afrika_cholmcc": {
    "AHGC": {
      "1.1.0": {
        "vassal+AHGC.png": {
          "url": "https://obj.vassalengine.org/gls/5/2/vassal+AHGC.png",
          "published_at": "2025-06-18T07:53:17.284368867Z",
          "published_by": "cholmcc"
        }
      }
    },
    "Colourful": {
      "1.1.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/7/6/vassal.png",
          "published_at": "2025-06-18T07:53:42.996040493Z",
          "published_by": "cholmcc"
        }
      }
    },
    "SPI": {
      "1.1.0": {
        "vassal+SPI.png": {
          "url": "https://obj.vassalengine.org/gls/b/6/vassal+SPI.png",
          "published_at": "2025-06-18T07:54:07.914822762Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "the_drive_on_metz_cholmcc": {
    "Module": {
      "1.0.0": {
        "vassal.png": {
          "url": "https://obj.vassalengine.org/gls/4/d/vassal.png",
          "published_at": "2025-06-18T10:36:46.203199243Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "the_drive_on_metz_2nd_ed_davout": {
    "Module": {
      "1.0.0": {
        "Domsamp.png": {
          "url": "https://obj.vassalengine.org/gls/3/b/Domsamp.png",
          "published_at": "2025-06-18T10:25:52.967679609Z",
          "published_by": "cholmcc"
        }
      }
    }
  },
  "the_battle_of_agincourt_kevos4": {
    "Module": {
      "1.0.0": {
        "BoA_Img1.png": {
          "url": "https://obj.vassalengine.org/gls/0/4/BoA_Img1.png",
          "published_at": "2025-06-18T20:04:08.739837804Z",
          "published_by": "cholmcc"
        }
      }
    }
  }
}

Format is

project_name : {
  package_name : {
    release_name : {
      image_name : {
        url: ...,
        published_by: username,
        published_at: date,
      }
    }
  }
}

Something like

SELECT project_id FROM projects WHERE project_name = project_name
SELECT package_id FROM packages WHERE project_id = project_id AND package_name = package_name 
SELECT release_id FROM releases WHERE package_id = package_id and version = release_name
SELECT user_id FROM users WHERE username = username
DELETE FROM files WHERE release_id = release_id AND filename = image_name
INSERT INTO images (project_id, filename, url, published_at, published_by )
  VALUES  (project_id, image_name, url, published_at, user_id)

should do the trick.

Yours,
Christian

OK, here’s the data slightly better formatted

{
  "afrika_korps_wga": {
    "Module": {
      "2.3.1": {
        "AFK-2.3.1.vmod": {
          "authors": [
            "wga"
          ],
          "published_by": "wga",
          "published_at": 1588802400,
          "requires": "3.2.17",
          "size": 3052439,
          "sha256": "02ff5c30b20b2fa334546c1841de61d3035fe21d7ebc41e0b0c704b168eafe0e",
          "url": "https://obj.vassalengine.org/gls/0/2/AFK-2.3.1.vmod"
        }
      },
      "2.3.0": {
        "AFK-2.3.vmod": {
          "authors": [
            "wga"
          ],
          "published_by": "wga",
          "published_at": 1588802400,
          "requires": "3.2.17",
          "size": 3068117,
          "sha256": "57fc5c65b627fa07803de3380df2295df648f05aaa1fb2c6d053702ee50d851a",
          "url": "https://obj.vassalengine.org/gls/5/7/AFK-2.3.vmod"
        }
      },
      "2.2.2": {
        "AFKv222.vmod": {
          "authors": [
            "Brent_Easton",
            "wga",
            "jw62",
            "unknown"
          ],
          "published_by": "Brent_Easton",
          "published_at": 1268002800,
          "requires": "3.1.12",
          "size": 3259363,
          "sha256": "b3b5aa2157767741f772ea05e3b55dea4230f21717053ec48fae9f60cfa848ba",
          "url": "https://obj.vassalengine.org/gls/b/3/AFKv222.vmod"
        }
      }
    },
    "Supporting Material": {
      "1.0.0": {
        "Afrika_Korps_Documents.zip": {
          "authors": [
            "Charles_McLellan"
          ],
          "published_by": "Charles_McLellan",
          "published_at": 1287352800,
          "requires": "n/a",
          "size": 5488715,
          "sha256": "52e62debbb1d3e5b0b36c6e407cf32b98a056c28edfb5127ca9298ca6484ec6e",
          "url": "https://obj.vassalengine.org/gls/5/2/Afrika_Korps_Documents.zip"
        }
      }
    }
  },
  "afrika_korps_stiglr": {
    "Module": {
      "1.0.1": {
        "Afrika_Korps_REV_Map_1.01.vmod": {
          "authors": [
            "Stiglr"
          ],
          "published_by": "Stiglr",
          "published_at": 1711321200,
          "requires": "3.2.17",
          "size": 7968935,
          "sha256": "6ed4fae82d3201751c670a06e1edeb67b4efd7e002f9e267fbf7c3f87b4165e2",
          "url": "https://obj.vassalengine.org/gls/6/e/Afrika_Korps_REV_Map_1.01.vmod"
        }
      }
    }
  },
  "afrika_korps_cgmclellan": {
    "Module": {
      "1.1.1": {
        "Afrika_Korps2_1.1.1.vmod": {
          "authors": [
            "Charles_McLellan",
            "unknown"
          ],
          "published_by": "Charles_McLellan",
          "published_at": 1404079200,
          "requires": "3.2.11+",
          "size": 2319135,
          "sha256": "20678136ff7d2761febb9c95b966b2525fee070a5d1c3368a5d6e06f3ddd8783",
          "url": "https://obj.vassalengine.org/gls/2/0/Afrika_Korps2_1.1.1.vmod"
        }
      },
      "1.0.0": {
        "Afrika_Korps2.vmod": {
          "authors": [
            "Charles_McLellan"
          ],
          "published_by": "Charles_McLellan",
          "published_at": 1286143200,
          "requires": "3.1.14+",
          "size": 2319197,
          "sha256": "9eca2a632508810f873604fd482d416eb0e6daa381bff2c3af717e5ab01187e1",
          "url": "https://obj.vassalengine.org/gls/9/e/Afrika_Korps2.vmod"
        }
      }
    },
    "Supporting Material": {
      "1.0.0": {
        "Afrika_Korps_Documents.zip": {
          "authors": [
            "Charles_McLellan"
          ],
          "published_by": "Charles_McLellan",
          "published_at": 1287352800,
          "requires": "n/a",
          "size": 5488715,
          "sha256": "52e62debbb1d3e5b0b36c6e407cf32b98a056c28edfb5127ca9298ca6484ec6e",
          "url": "https://obj.vassalengine.org/gls/5/2/Afrika_Korps_Documents.zip"
        }
      }
    }
  },
  "afrika_korps_cholmcc": {
    "Colourful": {
      "2.1.0": {
        "AfrikaKorps-2.1-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1707174000,
          "requires": "3.6",
          "size": 6277234,
          "sha256": "66a926aef8739c2f3a069afa100793234bb69e0444edda4c3139440380f10162",
          "url": "https://obj.vassalengine.org/gls/6/6/AfrikaKorps-2.1-ch.vmod"
        }
      },
      "2.0.0": {
        "AfrikaKorps-2.0-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1676156400,
          "requires": "3.6",
          "size": 5583135,
          "sha256": "9f285af95c40684b72fe44f77f042dab8d319dbcb9351418d6159fb20a9b1fcc",
          "url": "https://obj.vassalengine.org/gls/9/f/AfrikaKorps-2.0-ch.vmod"
        }
      },
      "1.1.0": {
        "AfrikaKorps-1.1-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1670194800,
          "requires": "3.6",
          "size": 5809043,
          "sha256": "a954e472b779c7698923721fa44202c86687fbfc70a9f953486697cdbb3a597a",
          "url": "https://obj.vassalengine.org/gls/a/9/AfrikaKorps-1.1-ch.vmod"
        }
      }
    },
    "Ol'School": {
      "2.1.0": {
        "AfrikaKorps-2.1-ch-oldschool.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1707174000,
          "requires": "3.6",
          "size": 6320410,
          "sha256": "82f4809f57ffa51757113606d51cfb7b8bcf22e1b10f153ada54985a0efc0033",
          "url": "https://obj.vassalengine.org/gls/8/2/AfrikaKorps-2.1-ch-oldschool.vmod"
        }
      },
      "2.0.0": {
        "AfrikaKorps-2.0-ch-oldschool.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1676156400,
          "requires": "3.6",
          "size": 5833247,
          "sha256": "ed9e97ad3bd915445c659787106818027202ae38c607d4e63c4dcdbedfa769eb",
          "url": "https://obj.vassalengine.org/gls/e/d/AfrikaKorps-2.0-ch-oldschool.vmod"
        }
      },
      "1.1.0": {
        "AfrikaKorps-1.1-ch-oldschool.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1670194800,
          "requires": "3.6",
          "size": 5831782,
          "sha256": "57b9df3fc8ef9096cc70c5968bc3a907edbbb2b5ae833458d21000d16f620546",
          "url": "https://obj.vassalengine.org/gls/5/7/AfrikaKorps-1.1-ch-oldschool.vmod"
        }
      }
    }
  },
  "anzio_beachhead_unknown": {
    "Module": {
      "1.1.0": {
        "Anzio_Beachhead_v1.1.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1635631200,
          "requires": "3.5.8",
          "size": 2446104,
          "sha256": "94a6617bbc7d5cb3600b85a208c0d2e19109448c6a067066c4853235e0b72e61",
          "url": "https://obj.vassalengine.org/gls/9/4/Anzio_Beachhead_v1.1.vmod"
        }
      }
    }
  },
  "anzio_beachhead_cholmcc": {
    "Module": {
      "1.0.1": {
        "AnzioBeachhead-ch-1.0.1.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1746655200,
          "requires": "3.7",
          "size": 5148791,
          "sha256": "34dcbea388c349494281a8695d176e1ee1f22de315599f74c8cabbaaa064f498",
          "url": "https://obj.vassalengine.org/gls/3/4/AnzioBeachhead-ch-1.0.1.vmod"
        }
      }
    }
  },
  "battle_skala": {},
  "battle_cholmcc": {
    "Module": {
      "1.0.0": {
        "Battle.vmod": {
          "authors": [
            "Skalla"
          ],
          "published_by": "Skalla",
          "published_at": 1040166000,
          "requires": "?",
          "size": 2349351,
          "sha256": "de90b560d81ab147d6b10fed14f72ecf9807fb4223fdf5139717db011343c039",
          "url": "https://obj.vassalengine.org/gls/d/e/Battle.vmod"
        }
      }
    }
  },
  "battle_for_moscow_operation_typhoon_olivier": {
    "Module": {
      "1.0.3": {
        "BFM-1.0.3.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1660428000,
          "requires": "3.5",
          "size": 5726609,
          "sha256": "3c48760533c9ecde7e0af407e254604c9f79e2219c17f4c57fd3e6ba81683d34",
          "url": "https://obj.vassalengine.org/gls/3/c/BFM-1.0.3.vmod"
        }
      },
      "1.0.2": {
        "BFM-1.0.2.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1634767200,
          "requires": "3.5",
          "size": 5729604,
          "sha256": "534b0123c8ef8a72d7695dca2a70c00951b75dbc617042dd1f0483ddea890f26",
          "url": "https://obj.vassalengine.org/gls/5/3/BFM-1.0.2.vmod"
        }
      },
      "1.0.1": {
        "BFM-1.0.1.vmod": {
          "authors": [
            "Olivier"
          ],
          "published_by": "Olivier",
          "published_at": 1614898800,
          "requires": "3.5",
          "size": 5712358,
          "sha256": "3df4fd36b79fe3e32dd30542a28dcd18980c68eff82c20aaae966bc18f2572d6",
          "url": "https://obj.vassalengine.org/gls/3/d/BFM-1.0.1.vmod"
        }
      },
      "1.0.0": {
        "BFM.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1302040800,
          "requires": "3.1.12",
          "size": 5726798,
          "sha256": "50791c450a07aa9b1266c7e8d6f03bea0f275013503cd7126d7a7e736d96e18a",
          "url": "https://obj.vassalengine.org/gls/5/0/BFM.vmod"
        }
      }
    }
  },
  "battle_for_moscow_operation_typhoon_expansion_json99": {
    "Module": {
      "2.0.0": {
        "Battle_for_Moscow_Expan_and_Winter_Off_2.0.vmod": {
          "authors": [
            "Olivier",
            "DaveJM",
            "unknown"
          ],
          "published_by": "Olivier",
          "published_at": 1652133600,
          "requires": "3.5",
          "size": 44810435,
          "sha256": "85f81d5c8b26bcdab70e8f01121321840e40e331ceb1610f86317a2170c834d2",
          "url": "https://obj.vassalengine.org/gls/8/5/Battle_for_Moscow_Expan_and_Winter_Off_2.0.vmod"
        }
      }
    }
  },
  "battle_for_moscow_unknown": {
    "Module": {
      "1.2.0": {
        "BattleforMoscow.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1128031200,
          "requires": "2.1",
          "size": 170210,
          "sha256": "037311bb6331af89db33561b1f766e5cff02822d4279a1054b1fcd2128072220",
          "url": "https://obj.vassalengine.org/gls/0/3/BattleforMoscow.vmod"
        }
      }
    }
  },
  "battle_for_moscow_cholmcc": {
    "Module": {
      "1.0.0": {
        "BattleForMoscow-ch-1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1674428400,
          "requires": "3.6",
          "size": 2662578,
          "sha256": "00dfc3e26df352628463f84b437d7dd3d4fd2883155cf9173ebbfb813056003f",
          "url": "https://obj.vassalengine.org/gls/0/0/BattleForMoscow-ch-1.0.vmod"
        }
      }
    }
  },
  "d_day_2nd_ed_brian448": {
    "Modules": {
      "2.0.2": {
        "D-Day-v202.vmod": {
          "authors": [
            "brian448",
            "unknown"
          ],
          "published_by": "brian448",
          "published_at": 1269126000,
          "requires": "3.1.14",
          "size": 3292010,
          "sha256": "b64cf7e857a832cd5c7d0f482e6bc682beaf7b1fc01b9f948ce0674e40438e9a",
          "url": "https://obj.vassalengine.org/gls/b/6/D-Day-v202.vmod"
        },
        "DDayVolkssturm.vmod": {
          "authors": [
            "Gordon_Cerow"
          ],
          "published_by": "Gordon_Cerow",
          "published_at": 1629928800,
          "requires": "3.5.7",
          "size": 23054525,
          "sha256": "ad5281e9930bd8ba7b46917de253f991736955ec3a568a4b497d78f3fa5cfcd0",
          "url": "https://obj.vassalengine.org/gls/a/d/DDayVolkssturm.vmod"
        }
      },
      "1.0.0": {
        "D-Day.vmod": {
          "authors": [
            "brian448"
          ],
          "published_by": "brian448",
          "published_at": 1257116400,
          "requires": "3.1.12",
          "size": 3182163,
          "sha256": "a5f8f77cc35428ea61d3b8075b39c96e2a490f7d2bdfff32e0f33c2fe167aace",
          "url": "https://obj.vassalengine.org/gls/a/5/D-Day.vmod"
        }
      }
    },
    "Supporting Material": {
      "0.0.0": {
        "D-Day_Basic_Game_Rules_1965_edition.pdf": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1750252100,
          "requires": "n/a",
          "size": 1310354,
          "sha256": "f3b4224ee6a874582510ddc02dd1378687eecd57e4850c33080bb7cd4a2831a4",
          "url": "https://obj.vassalengine.org/gls/f/3/D-Day_Basic_Game_Rules_1965_edition.pdf"
        },
        "D-Day_Tournament_Rules_1965_edition.pdf": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1750252086,
          "requires": "n/a",
          "size": 4063203,
          "sha256": "020bb7249bc424fa5ac1bc5b649f6d35e5b158d7cd0f348640cde0de642d7246",
          "url": "https://obj.vassalengine.org/gls/0/2/D-Day_Tournament_Rules_1965_edition.pdf"
        },
        "TAHGC_D-Day_Rulebook-100313.pdf": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1750252111,
          "requires": "n/a",
          "size": 4720721,
          "sha256": "c954d8d0d8de8c350bcc5bba84da7394d524da7c64d5fac89bc790411510cb20",
          "url": "https://obj.vassalengine.org/gls/c/9/TAHGC_D-Day_Rulebook-100313.pdf"
        },
        "Using_the_D-Day_Module.pdf": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1750252124,
          "requires": "n/a",
          "size": 122536,
          "sha256": "f2be100d9a88ed66216d9d880b9848e65f6f47597c5462d4ad7826186c2b3e6e",
          "url": "https://obj.vassalengine.org/gls/f/2/Using_the_D-Day_Module.pdf"
        }
      }
    }
  },
  "d_day_3rd_ed_crispy1critter": {
    "Module": {
      "1.1.0": {
        "D-DAY-77-1.1.vmod": {
          "authors": [
            "crispy1critter"
          ],
          "published_by": "crispy1critter",
          "published_at": 1533333600,
          "requires": "3.2.17",
          "size": 9104156,
          "sha256": "5a1dd869264b2a8e940e5b1c508e2398524a63478e2dc05394eed63346b15be8",
          "url": "https://obj.vassalengine.org/gls/5/a/D-DAY-77-1.1.vmod"
        }
      }
    }
  },
  "d_day_3rd_ed_woody8297": {
    "Module": {
      "3.0.0": {
        "D-Day-v3.0a.vmod": {
          "authors": [
            "woody8297"
          ],
          "published_by": "woody8297",
          "published_at": 1699916400,
          "requires": "3.7.5",
          "size": 6308284,
          "sha256": "5b35efe6b3ba984a9f44abd4ec2706a027de8e521070dbc067eddefd610334fb",
          "url": "https://obj.vassalengine.org/gls/5/b/D-Day-v3.0a.vmod"
        }
      }
    }
  },
  "d_day_3rd_ed_cholmcc": {
    "Colourful": {
      "1.0.0": {
        "DDay-1.0-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1666908000,
          "requires": "3.6.7",
          "size": 9351641,
          "sha256": "6c73de5ee54053c85675de8b310ae6a18a6e24dc81070949d6cf6536b695555e",
          "url": "https://obj.vassalengine.org/gls/6/c/DDay-1.0-ch.vmod"
        }
      }
    },
    "Ol'School": {
      "1.0.0": {
        "DDay-1.0-ch-oldschool.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1666908000,
          "requires": "3.6.7",
          "size": 7563607,
          "sha256": "dfcebf88563f4337f62d6ae18dc58f505964f4dcc53abdbe8f9a24f76a4cb36a",
          "url": "https://obj.vassalengine.org/gls/d/f/DDay-1.0-ch-oldschool.vmod"
        }
      }
    }
  },
  "gettysburg_125th_anniversary_wga": {
    "Module": {
      "3.4.0": {
        "G88v34.vmod": {
          "authors": [
            "Brent_Easton",
            "wga",
            "jw62"
          ],
          "published_by": "Brent_Easton",
          "published_at": 1618092000,
          "requires": "3.1.27",
          "size": 3057609,
          "sha256": "ee1cbcf0e4ac80047215a899cc0b37f9430b9b01d210bdc0fa336e3fabdae831",
          "url": "https://obj.vassalengine.org/gls/e/e/G88v34.vmod"
        }
      },
      "3.3.11": {
        "G88v33b11.vmod": {
          "authors": [
            "Brent_Easton",
            "wga",
            "jw62"
          ],
          "published_by": "Brent_Easton",
          "published_at": 1468706400,
          "requires": "3.1.20",
          "size": 2845791,
          "sha256": "233f231698cb87700363163e2ab8d1c7392da54ac6ba3429ab9c4f8cae543a7d",
          "url": "https://obj.vassalengine.org/gls/2/3/G88v33b11.vmod"
        }
      },
      "3.3.10": {
        "Campaign-130405.vsav": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1364853600,
          "requires": "3.1.20",
          "size": 7809,
          "sha256": "d4925e2d05bd207d8fe55ebec915814973565c279648ed01306e92245d0b776b",
          "url": "https://obj.vassalengine.org/gls/d/4/Campaign-130405.vsav"
        },
        "G88v33b10.vmod": {
          "authors": [
            "Brent_Easton",
            "wga",
            "jw62"
          ],
          "published_by": "Brent_Easton",
          "published_at": 1366063200,
          "requires": "3.1.20",
          "size": 2834168,
          "sha256": "463190fd9073d5c508a642602190a3699f89c4da0818d0a8a5a7ec5374bf722f",
          "url": "https://obj.vassalengine.org/gls/4/6/G88v33b10.vmod"
        }
      }
    }
  },
  "gettysburg_125th_anniversary_cholmcc": {
    "Module": {
      "1.2.0": {
        "GettysburgSmithsonian-1.2.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1707087600,
          "requires": "3.6",
          "size": 12231397,
          "sha256": "7ba3924ee2e55e4a490a325c48f93228baa05e8bbcda3978ed12b6fdbafb96c2",
          "url": "https://obj.vassalengine.org/gls/7/b/GettysburgSmithsonian-1.2.vmod"
        }
      },
      "1.1.0": {
        "GettysburgSmithsonian-1.1.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1691272800,
          "requires": "3.6",
          "size": 12355790,
          "sha256": "e0ac6f795f10cfb32eebfdd10756bb27d007b1167c2f1e10b438a45ae0ad3285",
          "url": "https://obj.vassalengine.org/gls/e/0/GettysburgSmithsonian-1.1.vmod"
        }
      },
      "1.0.0": {
        "GettysburgSmithsonian-1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1689372000,
          "requires": "3.6",
          "size": 12301770,
          "sha256": "4c6a5b8333a8b8b4e674b50d3a0c841afba7cae24c6e9d2e479831b4ca823dc8",
          "url": "https://obj.vassalengine.org/gls/4/c/GettysburgSmithsonian-1.0.vmod"
        }
      }
    }
  },
  "napoleon_at_waterloo_2nd_ed_stephen_oliver": {
    "Module": {
      "2.2.0": {
        "Napoleon_at_Waterloo_2nd_Ed_Vers_2.2.vmod": {
          "authors": [
            "iam2509"
          ],
          "published_by": "iam2509",
          "published_at": 1627768800,
          "requires": "3.5.3",
          "size": 12468448,
          "sha256": "9aeb91c3387ea4d7aee41396903f54e31333e06064f0828a257e3aa9ca5d558e",
          "url": "https://obj.vassalengine.org/gls/9/a/Napoleon_at_Waterloo_2nd_Ed_Vers_2.2.vmod"
        }
      }
    }
  },
  "napoleon_at_waterloo_3rd_ed_davejm": {
    "Module": {
      "1.1.0": {
        "Napoleon_at_Waterloo_SPI_V1.1.vmod": {
          "authors": [
            "DaveJM",
            "iam2509"
          ],
          "published_by": "DaveJM",
          "published_at": -61378303820,
          "requires": "3.7.14",
          "size": 40996515,
          "sha256": "0a316de6e15fbdc2f0a6ab1c31443a0635476ad7341b25bd3a23adc1cd804113",
          "url": "https://obj.vassalengine.org/gls/0/a/Napoleon_at_Waterloo_SPI_V1.1.vmod"
        }
      },
      "1.0.0": {
        "Napoleon_at_Waterloo_SPI_V1.0.vmod": {
          "authors": [
            "DaveJM",
            "iam2509"
          ],
          "published_by": "DaveJM",
          "published_at": -61464963020,
          "requires": "3.5.8",
          "size": 10583868,
          "sha256": "f33fda0774735be4d7ccb2a51e778142fb4435123125df7c53f5640419447e7c",
          "url": "https://obj.vassalengine.org/gls/f/3/Napoleon_at_Waterloo_SPI_V1.0.vmod"
        }
      }
    }
  },
  "napoleon_at_waterloo_cholmcc": {
    "Module": {
      "1.1.0": {
        "NapoleonAtWaterloo-ch-1.1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1713996000,
          "requires": "3.6",
          "size": 8519598,
          "sha256": "ab4a7e914e8bcc4651dfd2b01d07cee18761785be5ba84494aa4ebc8e990e93b",
          "url": "https://obj.vassalengine.org/gls/a/b/NapoleonAtWaterloo-ch-1.1.0.vmod"
        }
      },
      "1.0.0": {
        "NapoleonAtWaterloo-1.0-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1713996000,
          "requires": "3.6",
          "size": 8399943,
          "sha256": "f48e6341a6570045667b7c512008ddd979cdfc4486dca54a3f9d8c23b9f628ea",
          "url": "https://obj.vassalengine.org/gls/f/4/NapoleonAtWaterloo-1.0-ch.vmod"
        }
      }
    }
  },
  "panzerarmee_afrika_gamer94501": {
    "Module": {
      "0.0.1": {
        "PanzerArmeeAfrika-001d.vmod": {
          "authors": [
            "gamer94501"
          ],
          "published_by": "gamer94501",
          "published_at": 1431900000,
          "requires": "3.2.15",
          "size": 18385075,
          "sha256": "90e57d0ce477f9e189dd791ff4f9a7fbce18505dc19dd2f8cef7bc6b440d6295",
          "url": "https://obj.vassalengine.org/gls/9/0/PanzerArmeeAfrika-001d.vmod"
        },
        "PanzerArmeeAfrika-001e.vmod": {
          "authors": [
            "gamer94501"
          ],
          "published_by": "gamer94501",
          "published_at": 1433023200,
          "requires": "3.2.15",
          "size": 27718279,
          "sha256": "f41ba85f24e9397b8c38e821ca7a060ce99c30534c5dff03751389dea81a73ee",
          "url": "https://obj.vassalengine.org/gls/f/4/PanzerArmeeAfrika-001e.vmod"
        }
      }
    }
  },
  "panzerarmee_afrika_william_hay_spi": {
    "Module": {
      "3.2.0": {
        "PanzerArmeeAfrika_v32.vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1615762800,
          "requires": "3.5.2",
          "size": 14484046,
          "sha256": "84929046b330b9c0b11aacfb7f07fff0767d97c0c9f200f710746cf1476673d6",
          "url": "https://obj.vassalengine.org/gls/8/4/PanzerArmeeAfrika_v32.vmod"
        }
      }
    },
    "Module - AH": {
      "1.0.0": {
        "PanzerArmeeAfrika(SPI-AH).vmod": {
          "authors": [],
          "published_by": "unknown",
          "published_at": 1615762800,
          "requires": "3.5.2",
          "size": 10912622,
          "sha256": "596b9c7153484d3ed64ad39e88e4d116f8e4bf02fe42ab37cea8c2bf6e99fba4",
          "url": "https://obj.vassalengine.org/gls/5/9/PanzerArmeeAfrika(SPI-AH).vmod"
        }
      }
    }
  },
  "panzerarmee_afrika_luc_liu": {
    "Module": {
      "1.3.5": {
        "PanzerArmeeAfrika(SPI-AH)_v135.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1732316400,
          "requires": "3.7.15",
          "size": 11403371,
          "sha256": "6e214bf76e3ded7da0b7767e5861da0837fa726f0be308df0e47b296eb8b8492",
          "url": "https://obj.vassalengine.org/gls/6/e/PanzerArmeeAfrika(SPI-AH)_v135.vmod"
        }
      },
      "1.3.4": {
        "PanzerArmeeAfrika(SPI-AH)_v134.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1730156400,
          "requires": "3.7.14",
          "size": 11453090,
          "sha256": "cab3a6940832ae1c033cea3836db13c82d608f14df1ff2c283db23f04ee5e856",
          "url": "https://obj.vassalengine.org/gls/c/a/PanzerArmeeAfrika(SPI-AH)_v134.vmod"
        }
      },
      "1.3.3": {
        "PanzerArmeeAfrika(SPI-AH)_v133.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1729116000,
          "requires": "3.7.14",
          "size": 11457582,
          "sha256": "66b3105de8f61b27cf123d65d0ee86827aabac4d145cf50a3fdd907055bb483e",
          "url": "https://obj.vassalengine.org/gls/6/6/PanzerArmeeAfrika(SPI-AH)_v133.vmod"
        }
      },
      "1.3.2": {
        "PanzerArmeeAfrika(SPI-AH)_v132.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1723154400,
          "requires": "3.7.13",
          "size": 11377511,
          "sha256": "bf375129ab3b6eb99994bd84e161883c2830d2ba6f13d4ccd0f7740a9e1dc4f4",
          "url": "https://obj.vassalengine.org/gls/b/f/PanzerArmeeAfrika(SPI-AH)_v132.vmod"
        }
      },
      "1.3.1": {
        "PanzerArmeeAfrika(SPI-AH)_v131.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1719698400,
          "requires": "3.7.12",
          "size": 11388599,
          "sha256": "87ce466572b003577610bd961c4bc166f7aa57a862b0177eeeba15ab50ea4e9b",
          "url": "https://obj.vassalengine.org/gls/8/7/PanzerArmeeAfrika(SPI-AH)_v131.vmod"
        }
      },
      "1.3.0": {
        "PanzerArmeeAfrika(SPI-AH)_v130.vmod": {
          "authors": [
            "Luc_Liu"
          ],
          "published_by": "Luc_Liu",
          "published_at": 1717970400,
          "requires": "3.7.12",
          "size": 11353932,
          "sha256": "48ba924ea1f1a35e0da54229af9874ffc1569a9de45b0c1ed1ab3476ee58f5a6",
          "url": "https://obj.vassalengine.org/gls/4/8/PanzerArmeeAfrika(SPI-AH)_v130.vmod"
        }
      }
    }
  },
  "panzerarmee_afrika_cholmcc": {
    "AHGC": {
      "1.1.0": {
        "PanzerarmeeAfrika+AHGC-ch-1.1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1736118000,
          "requires": "3.7.0",
          "size": 10467357,
          "sha256": "0e0f055f7c7d9359a13a58471f3ffb0e98476a8fae46f9774ad33e6f037f3035",
          "url": "https://obj.vassalengine.org/gls/0/e/PanzerarmeeAfrika+AHGC-ch-1.1.0.vmod"
        }
      }
    },
    "Colourful": {
      "1.1.0": {
        "PanzerarmeeAfrika-ch-1.1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1736118000,
          "requires": "3.7.0",
          "size": 10392149,
          "sha256": "dc188da680f6de8611208cce301005c5fba08d68556b222576658948b3f2f238",
          "url": "https://obj.vassalengine.org/gls/d/c/PanzerarmeeAfrika-ch-1.1.0.vmod"
        }
      }
    },
    "SPI": {
      "1.1.0": {
        "PanzerarmeeAfrika+SPI-ch-1.1.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1736118000,
          "requires": "3.7.0",
          "size": 10123088,
          "sha256": "90b01e262093694f8cc938faf7faf5faff657325a87b56c58f8fe74b9939f2f1",
          "url": "https://obj.vassalengine.org/gls/9/0/PanzerarmeeAfrika+SPI-ch-1.1.0.vmod"
        }
      }
    }
  },
  "the_battle_of_agincourt_kevos4": {
    "Module": {
      "1.0.0": {
        "BoA_100.vmod": {
          "authors": [
            "KevOs4"
          ],
          "published_by": "KevOs4",
          "published_at": 1476568800,
          "requires": "3.2.16",
          "size": 1372230,
          "sha256": "f2e9a23a8476cdb3ddef531c1f3eba2f14aff6600c0cb4db11c7f2eae745b7e5",
          "url": "https://obj.vassalengine.org/gls/f/2/BoA_100.vmod"
        }
      }
    }
  },
  "3147": {
    "Module": {
      "1.0.0": {
        "BattleOfAgincourt-ch-1.0.0.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1746655200,
          "requires": "3.7",
          "size": 9983170,
          "sha256": "4e9ac50b96fedf2605dcb3a4d6488db23aabcde832b6d605037c266e5060a04b",
          "url": "https://obj.vassalengine.org/images/2/2a/BattleOfAgincourt-ch-1.0.0.vmod"
        }
      }
    }
  },
  "the_drive_on_metz_cholmcc": {
    "Module": {
      "1.0.0": {
        "DriveOnMetz-1.0-ch.vmod": {
          "authors": [
            "cholmcc"
          ],
          "published_by": "cholmcc",
          "published_at": 1690754400,
          "requires": "3.6+",
          "size": 2577539,
          "sha256": "d8a460f16a9cbb43b58b571fa639a32e7ae793fe222eb34df1283a1d44d45848",
          "url": "https://obj.vassalengine.org/gls/d/8/DriveOnMetz-1.0-ch.vmod"
        }
      }
    }
  },
  "the_drive_on_metz_2nd_ed_davout": {
    "Module": {
      "1.0.0": {
        "Metzv1.vmod": {
          "authors": [
            "Davout"
          ],
          "published_by": "Davout",
          "published_at": 1278194400,
          "requires": "3.0.17",
          "size": 1207507,
          "sha256": "864978536351bc18647b8407561bd8f60b9d88f3dbadfc858f1635815d6834ca",
          "url": "https://obj.vassalengine.org/gls/8/6/Metzv1.vmod"
        }
      }
    }
  }
}

Format is

project_name : {
  package_name : {
    release_name : {
      file_name : {
        authors: [ usernames ],
        published_by: username,
        published_at: date,
        requires: vassal-version,
        url: ...
      }
    }
  }
}

A set of SQL queries like above would seem to do the trick, e.g.,

SELECT project_id FROM projects WHERE project_name = project_name
SELECT package_id FROM packages WHERE project_id = project_id AND package_name = package_name 
SELECT release_id FROM releases WHERE package_id = package_id and version = release_name
SELECT user_id FROM users WHERE username = username
UPDATE files (...) VALUES (...) WHERE project_id == project_id AND filename = filename

Hopefully this will make life easier :slight_smile:

Yours,
Christian

Tried uploading the new file again today, this time getting a different error message:

Sounds good.

May I suggest, that you also add some hints to the various input forms. For example, in line 147 of PackageSection, you could add

<p>Release numbers <i>must</i> follow the conventions of 
  <a href="https://semver.org">Semantic Versioning</a> - i.e., be of the form 
  <i>Major</i>.<i>Minor</i>.<i>Patch</i> (and optional pre-release or build 
  information attached), where <i>Major</i>. <i>Minor</i>, and <i>Patch</i> 
  are whole, non-negative, numbers.
</p>
<p>
Examples of valid release versions are 
</p>
<pre>
1.2.3
10.20.30-alpha
6.4.0-rc1
5.3.8+french
</pre>

And in line 91 of PackagesSection, you add

<p>Package names are free-form strings, and structures the project into sub-parts.  
  A typical package name would be <code>Module</code></p>

And in line 123 of NewProjectPage something a la

<p>Project names consist solely of the letters <code>a,b,...,z</code>, 
  <code>A,B,...,Z</code>, digits <code>0,1,...,9</code>, dashes and underscores
  <code>-_</code>, and can be no longer than 64 characters.  Note that the project 
  name <i>must</i> start with a letter and <i>cannot</i> contain spaces, punctuation, 
  or other special characters.  
<p>Examples of good project names are 
<pre>
...
</pre>
</p>
</p>

And, of course, in line 177 of ReleaseSection

{#if !uploading}
<p>
  Remember that the version number of the module set <i>inside</i> the   
  module <i>must</i> be a valid <a href="https://semver.org">Semantic Version</a>,
  e.g., <code>1.2.3</code>.  The file name <i>should</i> contain the version number 
  too, but is not required to.  Also file name of should preferably not contain 
  spaces, punctuation, or special characters other than those in the version number,
  and as allowed by <a href="https://semver.org">Semantic Version</a> format.
</p>
<p>
  To set the version number in the module, open the module in the editor and 
  double click the top-level element.
</p>
{/if}

BTW, it seems that the version number inside the module does not need to match (or partially match) the release under which it is uploaded. Maybe I missed it somewhere in the code. Perhaps it would make sense to enforce that - at least that major, minor, and patch match, while pre-release and build info can be whatever.

In that way, the user will be alerted to the expectations right there and then when using the interface. This would go a long way toward preventing errors, I think.

Yours,
Christian

1 Like