@@ -702,9 +702,96 @@ static void ensure_update_manager(bool allow_downgrade)
702702 nullptr );
703703 }
704704
705+ vpkc_locator_config_t * locator_ptr = nullptr ;
706+
707+ #if LL_DARWIN
708+ // Try auto-detection first (works when the app bundle was packaged by vpk
709+ // and has UpdateMac + sq.version already present)
710+ if (!vpkc_new_update_manager_with_source (sUpdateSource , &options, nullptr , &sUpdateManager ))
711+ {
712+ char err[512 ];
713+ vpkc_get_last_error (err, sizeof (err));
714+ LL_INFOS (" Velopack" ) << " Auto-detect failed (" << ll_safe_string (err)
715+ << " ), falling back to explicit locator" << LL_ENDL;
716+
717+ // Auto-detection failed — construct an explicit locator.
718+ // This handles legacy DMG installs that don't have Velopack's
719+ // install state (UpdateMac, sq.version) in the bundle.
720+ vpkc_locator_config_t locator = {};
721+
722+ // The executable lives at <bundle>/Contents/MacOS/<exe>
723+ // The app bundle root is two levels up from the executable directory.
724+ std::string exe_dir = gDirUtilp ->getExecutableDir ();
725+ std::string bundle_root = exe_dir + " /../.." ;
726+ char resolved[PATH_MAX];
727+ if (realpath (bundle_root.c_str (), resolved))
728+ {
729+ bundle_root = resolved;
730+ }
731+
732+ // Construct a version string in Velopack SemVer format: major.minor.patch-build
733+ const LLVersionInfo& vi = LLVersionInfo::instance ();
734+ std::string current_version = llformat (" %d.%d.%d-%llu" ,
735+ vi.getMajor (), vi.getMinor (), vi.getPatch (), vi.getBuild ());
736+
737+ // Create a minimal sq.version manifest so Velopack knows our version.
738+ // Proper vpk-packaged builds have this in the bundle already.
739+ std::string manifest_path = gDirUtilp ->getExpandedFilename (LL_PATH_TEMP, " sq.version" );
740+ {
741+ std::string app_name = LLVersionInfo::instance ().getChannel ();
742+ std::string pack_id = app_name;
743+ pack_id.erase (std::remove (pack_id.begin (), pack_id.end (), ' ' ), pack_id.end ());
744+
745+ std::string nuspec = " <?xml version=\" 1.0\" encoding=\" utf-8\" ?>\n "
746+ " <package xmlns=\" http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd\" >\n "
747+ " <metadata>\n "
748+ " <id>" + pack_id + " </id>\n "
749+ " <version>" + current_version + " </version>\n "
750+ " <title>" + app_name + " </title>\n "
751+ " </metadata>\n "
752+ " </package>\n " ;
753+
754+ llofstream manifest_file (manifest_path, std::ios::trunc);
755+ if (manifest_file.is_open ())
756+ {
757+ manifest_file << nuspec;
758+ manifest_file.close ();
759+ }
760+ }
761+
762+ std::string packages_dir = gDirUtilp ->getExpandedFilename (LL_PATH_TEMP, " velopack-packages" );
763+ LLFile::mkdir (packages_dir);
764+
765+ locator.RootAppDir = const_cast <char *>(bundle_root.c_str ());
766+ locator.CurrentBinaryDir = const_cast <char *>(exe_dir.c_str ());
767+ locator.ManifestPath = const_cast <char *>(manifest_path.c_str ());
768+ locator.PackagesDir = const_cast <char *>(packages_dir.c_str ());
769+ locator.UpdateExePath = nullptr ;
770+ locator.IsPortable = false ;
771+
772+ locator_ptr = &locator;
773+
774+ LL_INFOS (" Velopack" ) << " Explicit locator: RootAppDir=" << bundle_root
775+ << " CurrentBinaryDir=" << exe_dir
776+ << " Version=" << current_version << LL_ENDL;
777+
778+ if (!vpkc_new_update_manager_with_source (sUpdateSource , &options, locator_ptr, &sUpdateManager ))
779+ {
780+ char err2[512 ];
781+ vpkc_get_last_error (err2, sizeof (err2));
782+ LL_WARNS (" Velopack" ) << " Failed to create update manager: " << ll_safe_string (err2) << LL_ENDL;
783+ }
784+ }
785+ return ;
786+ #endif
787+
788+ // Windows: Velopack auto-detection works because the viewer is installed
789+ // by Velopack's Setup.exe which creates the proper install structure.
705790 if (!vpkc_new_update_manager_with_source (sUpdateSource , &options, nullptr , &sUpdateManager ))
706791 {
707- LL_WARNS (" Velopack" ) << " Failed to create update manager" << LL_ENDL;
792+ char err[512 ];
793+ vpkc_get_last_error (err, sizeof (err));
794+ LL_WARNS (" Velopack" ) << " Failed to create update manager: " << ll_safe_string (err) << LL_ENDL;
708795 }
709796}
710797
0 commit comments