It seems that you're using an outdated browser. Some things may not work as they should (or don't work at all).
We suggest you upgrade newer and better browser like: Chrome, Firefox, Internet Explorer or Opera

×
So I've run into another issue.
The update worked fine, and it went through and created my manifest. So I went to verify what I had from before (new computer, same old storage drive), and it hit this error.

18:31:46 | mismatched file size for treasures_of_the_savage_frontier\treasures_of_the_savage_frontier_manual.zip
18:31:46 | cleaning treasures_of_the_savage_frontier\treasures_of_the_savage_frontier_manual.zip
18:31:46 | fatal...
Traceback (most recent call last):
File "D:\GOGBackup\gogrepoc.py", line 395, in __getattr__
return self[key]
~~~~^^^^^
KeyError: 'force_change'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "D:\GOGBackup\gogrepoc.py", line 4252, in <module>
main(process_argv(sys.argv))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 4050, in main
cmd_verify(args.gamedir, args.skipextras,args.skipids,check_md5, check_filesize, check_zips, args.delete,not args.noclean,args.ids, args.os, args.lang,args.skipgalaxy,args.skipstandalone,args.skipshared, args.skipfiles, args.forceverify,args.permissivechangeclear)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 3703, in cmd_verify
if (old_verify != itm.prev_verified or old_last_updated != itm.old_updated or itm.force_change != old_force_change):
^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 397, in __getattr__
raise AttributeError(key)
AttributeError: force_change


Thanks again
avatar
molerat: So I've run into another issue.
The update worked fine, and it went through and created my manifest. So I went to verify what I had from before (new computer, same old storage drive), and it hit this error.

18:31:46 | mismatched file size for treasures_of_the_savage_frontier\treasures_of_the_savage_frontier_manual.zip
18:31:46 | cleaning treasures_of_the_savage_frontier\treasures_of_the_savage_frontier_manual.zip
18:31:46 | fatal...
Traceback (most recent call last):
File "D:\GOGBackup\gogrepoc.py", line 395, in __getattr__
return self[key]
~~~~^^^^^
KeyError: 'force_change'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "D:\GOGBackup\gogrepoc.py", line 4252, in <module>
main(process_argv(sys.argv))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 4050, in main
cmd_verify(args.gamedir, args.skipextras,args.skipids,check_md5, check_filesize, check_zips, args.delete,not args.noclean,args.ids, args.os, args.lang,args.skipgalaxy,args.skipstandalone,args.skipshared, args.skipfiles, args.forceverify,args.permissivechangeclear)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 3703, in cmd_verify
if (old_verify != itm.prev_verified or old_last_updated != itm.old_updated or itm.force_change != old_force_change):
^^^^^^^^^^^^^^^^
File "D:\GOGBackup\gogrepoc.py", line 397, in __getattr__
raise AttributeError(key)
AttributeError: force_change

Thanks again
Hmmm, that's weird, one of your manifest entries and quiet a late one doesn't have force_change set, not sure how that could happen with a new manifest. Can you email your manifest file to my user name AT gmail DOT com please ? Will have to have a look at it to work out what's going on.

ETA - Probably found the source of the problem myself, now to add in some padding to avoid this crash.
Post edited April 01, 2025 by Kalanyr
Performing some final testing which should hopefully resolve any outstanding issues with the last release. Will upload it to dev shortly (and edit this when it is).

If you have any outstanding issue from the last week or so please try it out and let me know if it's resolved your issues.

Edit - Available from Dev now. Given the issues here and the relatively small scale of the changes I'll only give this one a 3 day feedback period before I role to main ( or I'll roll to main immediately if I get confirmation it fixes all outstanding problems )
Post edited April 01, 2025 by Kalanyr
avatar
lupineshadow: You can chmod +x the works of Shakespeare and then ./kinglear and it might have undefined behaviour but as far as I know Shakespeare didn't include rm -rf in any of his neologisms so maybe it's ok.
This is not the same, and you know that. Doing a "chmod +x" on a random natural language text file won't generally do anything bad, even if that language is english. Most programming languages, on the other hand, use english keywords from pretty much te same subset of words with similar meanings: "if", "then", "while", "print",… So the risk of unwanted side effects is greater by some orders of magnitude whenever you perform "chmod +x" on a source code file.
avatar
lupineshadow: I did the same as you incidentally and also got the Imagemagick screenshot crosshair and it freaked me out but otherwise there was no side-effects.
Imagine this happening to a non-programmer and non-sysadmin, please. There will be a bunch of leftover files not obviously being recognisable as images ("unicodedata", "os", "sys", "threading", "logging", "html5lib", "pprint", "time", "zipfile", "hashlib",… – until they give up clicking, or the last "import" quits), they won't know where they come from, whether those are safe to delete. They also might take harsh measures to recover, like a reboot via reset button, possibly losing hours of work.
avatar
lupineshadow: I imagine detrimental side-effects are as difficult to achieve as preventative guards.
Preventative guards are easy, you just don't like them because you consider them to be "bad programming style".

I think I've shown that the "hacky" solution prevents that from happening at least for the vast majority of shells, it is easier to maintain than any other solution, because everything can still be kept in one file. Having multiple files makes installation more difficult, since it introduces restrictions: the "outer" file must find the one(s) to execute, and no, instructing the user to put everything in one place is not sufficient.

Imagine you are in "$HOME", your scripts are in:
"$HOME/GOG-stuff/wrapper.sh"
and:
"$HOME/GOG-stuff/gogrepoc.py".
Those 2 calls are different:
1) cd $HOME/GOG-stuff ; ./wrapper.sh
2) GOG-stuff/wrapper.sh
In the latter case, "gogrepoc.py" isn't in the current directory, so a simple wrapper calling
"python gogrepoc.py $PARAMETERS"
won't work, so you you add complexity bei either giving instructions to the user, or adding code to find "gogrepoc.py" or to make sure it gets installed to a known location by an installer.

In addition, the wrapper doesn't prevent anyone from calling the other file directly. Depending on how it is written (example: assuming all executable and data files are in the current directory), it also forces the user to not follow the "Linux Filesystem Hierarchy Standard", where executable files related to gaming, and not packaged for the distribution, should reside in "/usr/local/games".

You want to enforce "clearness" and "good style" on the "programming end", but inevitably add complexity for the user, who is much less likely to handle that correctly.

Who answers questions of users failing? Who maintains the additional code?
Fair enough, it seems to work really well.

I had forgotten about the created files from ImageMagick and the fact that the screen capture crosshair repeats multiple times.

As a peace offering here is a version which gives you a bit more flexibility and also mypy (python linter) doesn't seem to complain about the wrapper (forum is going to remove the indentation unfortunately)

# -*- coding: utf-8 -*-

from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

if False:
"""
# "
cat >/dev/null <<SHELL_TRAP
"""
_SHELL_TRAP2 = 1
else:
#
#
#
# REST OF THE SCRIPT HERE, INDENTED FOR THE ELSE BLOCK
#
#
#
pass

# finally

exit(0)
"""
SHELL_TRAP
then
echo "--------------------------------------------------------------------------"
echo "You have tried to execute this script directly, which is not possible."
echo "Please run the script again, using python $(basename $0) (arguments)"
echo "--------------------------------------------------------------------------"
fi
exit 1
"""
$ ./gogrepoc.py
./gogrepoc.py: line 3: from: command not found
./gogrepoc.py: line 4: from: command not found
./gogrepoc.py: line 5: from: command not found
./gogrepoc.py: line 7: False:: command not found
./gogrepoc.py: line 9: $'\n# ': command not found
--------------------------------------------------------------------------
You have tried to execute this script directly, which is not possible.
Please run the script again, using python gogrepoc.py (arguments)
--------------------------------------------------------------------------

$ python gogrepoc.py
usage: gogrepoc.py [-h] [-v]
{login,update,download,import,backup,verify,clean,trash} ...
gogrepoc.py: error: the following arguments are required: command
Post edited April 03, 2025 by lupineshadow
avatar
lupineshadow: Fair enough, it seems to work really well.

I had forgotten about the created files from ImageMagick and the fact that the screen capture crosshair repeats multiple times.

As a peace offering here is a version which gives you a bit more flexibility and also mypy (python linter) doesn't seem to complain about the wrapper (forum is going to remove the indentation unfortunately)

# -*- coding: utf-8 -*-

from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

if False:
"""
# "
cat >/dev/null <<SHELL_TRAP
"""
_SHELL_TRAP2 = 1
else:
#
#
#
# REST OF THE SCRIPT HERE, INDENTED FOR THE ELSE BLOCK
#
#
#
pass

# finally

exit(0)
"""
SHELL_TRAP
then
echo "--------------------------------------------------------------------------"
echo "You have tried to execute this script directly, which is not possible."
echo "Please run the script again, using python $(basename $0) (arguments)"
echo "--------------------------------------------------------------------------"
fi
exit 1
"""
avatar
lupineshadow: $ ./gogrepoc.py
./gogrepoc.py: line 3: from: command not found
./gogrepoc.py: line 4: from: command not found
./gogrepoc.py: line 5: from: command not found
./gogrepoc.py: line 7: False:: command not found
./gogrepoc.py: line 9: $'\n# ': command not found
--------------------------------------------------------------------------
You have tried to execute this script directly, which is not possible.
Please run the script again, using python gogrepoc.py (arguments)
--------------------------------------------------------------------------

$ python gogrepoc.py
usage: gogrepoc.py [-h] [-v]
{login,update,download,import,backup,verify,clean,trash} ...
gogrepoc.py: error: the following arguments are required: command
Interesting, any chance you could upload it to pastebin or a gist or something ? I think the lack of formatting is losing something because I've read over it and while I understand the basic idea there's parts of it that don't seem to make sense.
Hmm. GOG is still definitely having problems marking some games as updated, my Eiyuden Chronlcles game didn't get marked despite the recent DLC release ( I think this might be related to the DLC not being marked as purchased if you're entitled to it through another purchase because unlike the previous DLC which shows as purchased this one does not ).
avatar
Kalanyr: Interesting, any chance you could upload it to pastebin or a gist or something ? I think the lack of formatting is losing something because I've read over it and while I understand the basic idea there's parts of it that don't seem to make sense.
Sure: https://pastebin.com/eV4kVb3F
avatar
Kalanyr: Interesting, any chance you could upload it to pastebin or a gist or something ? I think the lack of formatting is losing something because I've read over it and while I understand the basic idea there's parts of it that don't seem to make sense.
avatar
lupineshadow: Sure: https://pastebin.com/eV4kVb3F
Ahh, thanks I think that helped, the #finally is an actual comment, indicating that this is after the if/else ? I was trying to read it as part of the structure of either the shell script or python script and getting confused.
avatar
lupineshadow: Sure: https://pastebin.com/eV4kVb3F
avatar
Kalanyr: Ahh, thanks I think that helped, the #finally is an actual comment, indicating that this is after the if/else ? I was trying to read it as part of the structure of either the shell script or python script and getting confused.
Cool

Also I don't think the first # before the cat /dev/null> is needed, I took it out and it worked fine.
Rolled the patches to main.

@lupineshadow
Thank you again for the wrapper suggestion, I'll see about integrating it next time.
Hello again,

I hereby confirm the current non-dev version working unmodified here, except for possible side effetcs due to not having tried any "real commands" yet (because of a computer crash of the machine containing my game collection).

The "wakelock problem" is solved.

However, I found some minor issues, I'll begin with the most harmless: the documentation.

1) The version number is unmodified at "0.4.0-a".

In my opinion (can of course be forgotten, happens to me frequently), every change commited to the "stable" version should have its version number increased as well. The development branch can have something like "-current" appended to the "stable" version's number it is based on for convenience, I think, but having unique numbers on files of different contents greatly facilitates communication with users reporting issues, simply ask for the number, and you know what they're using.

2) The order of arguments in -h output and README.md

The order should be the same in every piece of documentation. Ideally, calling "python gogrepoc.py COMMAND -h" should produce the same output as is seen in the README section. The reason: the order is important, in the "-h" output you differentiate between "positional" and "optional" arguments. Technically, "positional" arguments ("savedir") can be optional as well, so the words are misleading, and there's no explanation what "positional" means.

At least I have been mislead by "[savedir] / [gamedir]" appearing at the end of the output of "… download / verify -h".
(Should be called the same as well, because it is the same thing, I think – I prefer "gamesdir".)

Testing revealed that the directory arguments may be the first, as well as follow an argument -SOMETHING that does not expect further parameters (those os and language lists, for example), if it appears directly after such a list, it is mistaken as part of that list.

So, to not confuse the user, I suggest the following:
A) Put any directory names immediately after the command everywhere (as the 1st argument).
B) Use the same order of other options everywhere: "in the short option list", as well as in the "description section", and also in the same order when they apply to several commands.
C) It would be nice to tell the user about the allowed values for "things" when using "-h".

This should result in a "safe" order when strictly followed.

Example for C):
------------8<------------------------------------------------
python /usr/local/games/gogrepoc.py verify -os BSD
20:38:14 | Could not initialise the systemd session inhibitor: QDBusReply value is invalid
20:38:14 | error: specified os "BSD" is not one of the valid os types [u'windows', u'linux', u'mac']
------------8<------------------------------------------------
Example for -h output:
------------8<------------------------------------------------
-os [OS [OS ...]] verify game files only for operating system(s)
valid OS values: windows, linux, mac
------------8<-----------------------------------------------

If you like, I can make a suggestion, and send you the diffs to the current files. (Please don't ask me to learn git for that, however…)
Post edited April 10, 2025 by ChFra
Another issue:

I tested once "download -covers -backgrounds"; it seems to me that those are now always fetched, even when not specified any more on the command line. If I remember correctly, there were no images downloaded before I tried that "explicitly" for the first time.

SORRY, PLEASE FORGET THIS, I MISPROGRAMMED MY OWN DOWNLOAD SCRIPT!
Post edited April 11, 2025 by ChFra
I'm attempting to add my existing GOG download folder to gogrepo and am getting a fatal error, possibly because of the folder paths?

C:\SendTo\gogrepo>python gogrepoc.py import "E:\Video Games\GamesA_M\" "E:\Video Games\GamesA_M\"
21:46:51 | fatal...
Traceback (most recent call last):
File "C:\SendTo\gogrepo\gogrepoc.py", line 4263, in <module>
main(process_argv(sys.argv))
File "C:\SendTo\gogrepo\gogrepoc.py", line 4021, in main
if args.clean:
^^^^^^^^^^
AttributeError: 'Namespace' object has no attribute 'clean'

My goal is to create a manifest of what I've already got so that I don't have to redownload everything just to get it in gogrepo's database. The existing folder is already set up how GOG sets up folders, it's from an earlier mass backup. I don't need or want to move all of these folders to a different folder, I just want gogrepo to see what's there. Is there a way to do that?
avatar
Gilozard: I'm attempting to add my existing GOG download folder to gogrepo and am getting a fatal error, possibly because of the folder paths?

C:\SendTo\gogrepo>python gogrepoc.py import "E:\Video Games\GamesA_M\" "E:\Video Games\GamesA_M\"
21:46:51 | fatal...
Traceback (most recent call last):
File "C:\SendTo\gogrepo\gogrepoc.py", line 4263, in <module>
main(process_argv(sys.argv))
File "C:\SendTo\gogrepo\gogrepoc.py", line 4021, in main
if args.clean:
^^^^^^^^^^
AttributeError: 'Namespace' object has no attribute 'clean'

My goal is to create a manifest of what I've already got so that I don't have to redownload everything just to get it in gogrepo's database. The existing folder is already set up how GOG sets up folders, it's from an earlier mass backup. I don't need or want to move all of these folders to a different folder, I just want gogrepo to see what's there. Is there a way to do that?
You shouldn't use import for what you're doing (though you have identified an error I need to fix). You should just do a (full) update, then gogrepoc will fix everything after a download + verify pointed at the folder you have everything in. Import is for importing installers in a different folder structure (like if you had an old GOG Downloader setup or a collection of manually downloaded files ).

I thought I set a default behaviour for clean in import but cleary not.

ETA - Whoops, that check was one option off, it's supposed to be in verify but I accidentally put it in import. Testing fix and will make an emergency hotfix shortly.
Post edited April 12, 2025 by Kalanyr